如何将平面映射转换为复杂的JSONObject? [英] How to transform a flat map to complex JSONObject?
问题描述
我想将平面键值映射转换为复杂的json对象.
I want to transform a flat key-value map into a complex json object.
结构如下:
- 地图键当然代表json键.
- 嵌套元素之间用点分隔
- 列表元素在键的末尾用数字表示.末尾可能有多个数字.不幸的是,这些键以相反的顺序站立.意味着第一个键片段"映射到最后一位,最里面的键片段映射到第一位.
以下示例:
service.fee.1.1=a
service.fee.2.1=b
service.fee.3.1=c
此处,服务"键始终映射到index = 1.这意味着服务"是一个数组,但是在这种情况下只有一个元素. 一个元素具有键"fee",其中包含3个值.
Here the "service" key maps always to index=1. This means "service" is an array, but with only one element in this case. The one element has the key "fee", with 3 values inside.
所得的json
因此应为:
{
"service": [
{
"fee": ["a", "b", "c"]
}
]
}
另一个例子:
service.fee.name.1.1=a
service.fee.age.2.1=b
service.fee.test.2.1=c
{
"service": [
{
"fee": [
{
"name": "a"
},
{
"age": "b",
"test": "c"
}
]
}
]
}
这就是我的开始,但是我无法理解可能必须使用递归来处理嵌套对象和列表的地方:
That's what I started with, but I cannot get the point where I probably have to use recursion to handle nested objects and lists:
JSONObject json = new JSONObject();
for (Map.Entry<String, String> entry : map.entrySet()) {
String key = entry.getKey();
if (endswithdigit(key)) {
} else {
if (key.contains("-")) {
//complex object
JSONObject subjson = new JSONObject();
json.put(key, subjson);
//TODO probably have to apply some kind of recursion here with subjson??
} else {
//plain value
json.put(key, entry.getValue());
}
}
}
也许您可以建议如何正确地构建具有嵌套列表和递归的嵌套JSONObject
?
Maybe you could give advise how to properly build a nested JSONObject
with nested lists and recursion?
推荐答案
如果您需要自己解决此问题(IE:一个库无法处理),那么我将其分解,以便可以通过复合模式.
If you need to tackle this problem yourself (IE: a library cannot handle it), then I would break it down so that it can be coherently tackled with Composite Pattern.
我将分两部分讨论这个答案:第一,是提出的用于创建层次结构的解决方案;第二,是解决方案.其次,如何利用Composite模式将内部层次结构转换为所需的JSON.
I'll address this answer in two parts: first, a proposed solution to create the heirarchy; and second, how to utilize the Composite pattern to turn your internal heirarchy into the JSON you want.
第1部分:创建继承人
一种解决方法是通过将元素划分为垃圾箱来迭代创建对象(从包含每个元素的公共复合根对象开始).这将形成数据的复合结构.流程将是:
One approach for this would be to iteratively create objects by dividing elements in to bins (starting with a common composite root object that contains every element). This will form the composite structure of your data. The flow will be:
- 对于对象组合箱中的每个元素:
- 从元素左侧剥离顶级标识符
- 创建要与其关联的标识符.
- 如果已键入密钥:
- 从右侧剥离钥匙
- 为标识符创建一个复合数组(如果不存在).
- 如果元素的
=
剩余数据,请执行以下操作:- 为与该数组索引关联的元素容器(如果不存在)创建一个复合对象.
- 将元素放入该对象的容器中.
- For each element in the bin of the object composite:
- Strip off the top-level identifier from the left of the element
- Create an identifier to be associated with it.
- If it is keyed:
- Strip off the key from the right
- Create a composite array for the identifier (if it does not exist).
- If there is further data left of the
=
of the element:- Create a composite object for the element bin associated with that array index (if it does not exist).
- Place the element in a bin for that object.
- 为与该数组索引关联的元素容器(如果不存在)创建一个复合对象.
- 将元素放入该对象的容器中.
例如,假设我们正在使用给定的数据集:
For example's sake, lets assume we are working with the given dataset:
x.y.z.1.1=A x.y.z.3.1=B x.y.w.1.1=C x.u.1=D a.b.1=E a.c.1=F e.1=G e.2=H i=I m.j=J m.k=K
该过程将如下:
ITERATION 0 (initialize): root // x.y.z.1.1=A, x.y.z.3.1=B, x.y.w.1.1=C, x.u.1=D, a.b.1=E, a.c.1=F, e.1=G, e.2=H, i=I, m.j=J, m.k=K ITERATION 1: root : x[1] // y.z.1=A, y.z.3=B, y.w.1=C, u=D a[1] // b=E, c=F e[1] : "G" e[2] : "H" i : "I" m : // j=J, k=K ITERATION 2: root : x[1] : y[1] // z=A, w=C y[3] // z=B u : "D" a[1] : b : "E" c : "F" e[1] : "G" e[2] : "H" i : "I" m : j : "J" k : "K" ITERATION 3: root : x[1] : y[1] : z : "A" w : "C" y[3] : z : "B" u: "D" a[1] : b : "E" c : "F" e[1] : "G" e[2] : "H" i : "I" m : j : "J" k : "K"
第2部分:复合模式
在这一点上,我们已经将数据迭代地划分为一个分层的复合结构.现在我们只需要将内部化的数据结构转换为JSON.这是复合模式会派上用场的地方;您的每个对象都将实现以下接口:
At this point, we've iteratively divided our data into a heirarchical composite structure; now we just need to get our internalized data structure into JSON. This is where the Composite pattern will come in handy; each of your objects will implement the following interface:
// All objects in the composite tree must implement this. public interface Jsonable { // The non-leaf objects will need to have their implementation of this // call it for each child object (and handle gaps). JsonObject toJsonObject(); }
如果遵循上述内容,我们可能会使用该接口的三个实现:
ArrayComposite
,ObjectComposite
和ValueLeaf
.If following the above, we would likely have three implementations of this interface:
ArrayComposite
,ObjectComposite
, andValueLeaf
.在根元素上调用
toJsonObject()
将为您提供完整的JsonObject
.下面是上述示例的结构化表示形式(请注意y
数组中添加的间隙;这需要在数组组合的toJsonObject()
调用中处理):Calling
toJsonObject()
on your root element will give you your completeJsonObject
. A textural representation of that for the above example is below (notice the added gap in they
array; this needs to be handled in thetoJsonObject()
call of your array composites):{ "x" : [ { "y" : [ { "z" : "A", "w" : "C" }, "", { "z" : "B" } ] } ], "a" : [ { "b" : "D", "c" : "E" } ], "e" : [ "F", "G" ] "i" : "I" "m" : { "j" : "J", "k" : "K" } }
您正在寻找忽略白色间距的地方.
Which, neglecting white spacing, seems to be what you're looking for.
请注意,这假设数据集不包含会导致无效JSON的元素. IE:数据集不能包含以下内容:
Note that this assumes a data set does not contain elements that would result in invalid JSON. IE: the dataset could not contain the following:
i=I i.1=I
可以说
i
既是数组又是值.As it would be saying that
i
is both an array and a value.这篇关于如何将平面映射转换为复杂的JSONObject?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!