我想将平面键值映射转换为复杂的json对象。
结构如下:
以下示例:
service.fee.1.1=a
service.fee.2.1=b
service.fee.3.1=c
这里的"服务"键映射始终为index = 1。这意味着"服务"是一个数组,但在这种情况下只有一个元素。 一个元素有关键"费用",里面有3个值。
结果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"
}
]
}
]
}
这就是我的开始,但我无法理解我可能必须使用递归来处理嵌套对象和列表:
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
?
答案 0 :(得分:1)
如果您需要自己解决这个问题(IE:库无法处理它),那么我会将其分解,以便可以使用Composite Pattern进行连贯处理。
我将分两部分来回答这个问题:第一,提出创建层次结构的解决方案;第二,如何利用Composite模式将内部层次转换为您想要的JSON。
第1部分:创建Heirarhcy
这种方法的一种方法是通过将元素划分为二进制来迭代地创建对象(从包含每个元素的公共复合根对象开始)。这将形成数据的复合结构。流程将是:
=
还有剩余数据:
=
还有剩余数据:
例如,假设我们正在使用给定的数据集:
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。这就是复合模式将派上用场的地方;您的每个对象都将实现以下接口:
// 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
。
在您的根元素上调用toJsonObject()
将为您提供完整的JsonObject
。以下示例的结构表示如下(注意y
数组中添加的间隙;这需要在数组合成的toJsonObject()
调用中处理):
{
"x" : [
{
"y" : [
{
"z" : "A",
"w" : "C"
},
"",
{
"z" : "B"
}
]
}
],
"a" : [
{
"b" : "D",
"c" : "E"
}
],
"e" : [
"F",
"G"
]
"i" : "I"
"m" : {
"j" : "J",
"k" : "K"
}
}
忽略白色间距似乎是你正在寻找的东西。
请注意,这假定数据集不包含会导致无效JSON的元素。 IE:数据集不能包含以下内容:
i=I
i.1=I
因为它会说i
既是数组又是值。
答案 1 :(得分:0)
请尝试使用Gson库并使用新的Gson()。toJson(yourmap);这会将您的地图转换为JSON格式。
答案 2 :(得分:0)
也许你通过拆分数字开始的键,并使用子键的LIFO和值和索引的FIFO来解决它。而不是拆分它可以通过解析密钥并检测数字的开始位置来完成:
例如:
x.y.z.2.1 = val
这是分开的,以显示它是如何工作的,但只需解析字符串就可以完成(:是分隔分隔)。
x.y.z : 2.1 : val
然后将子键放入LIFO(x先进入,最后进行z):
LIFO
head: z
y
x
和值和索引的FIFO(2先进入,val进去最后)
Fifo
top:2
1
val
然后你可以从LIFO中弹出并将它与FIFO的弹出相匹配。第一个赋值将是地图的值,然后,分配将完成到最后一步的对象或数组。
z = val
y[1] = z
x[2] = y