![](/img/trans.png)
[英]how to use java streams api to transform a hierarchal map to a flat map
[英]How to transform a flat map to complex JSONObject?
我想將平面鍵值映射轉換為復雜的 json 對象。
結構如下:
下面的例子:
service.fee.1.1=a
service.fee.2.1=b
service.fee.3.1=c
這里的“服務”鍵總是映射到 index=1。 這意味着“服務”是一個數組,但在這種情況下只有一個元素。 第一個元素有鍵“fee”,里面有 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
?
如果您需要自己解決這個問題(即:庫無法處理它),那么我會將其分解,以便可以使用Composite Pattern連貫地解決它。
我將分兩部分來回答這個答案:首先,提出的創建層次結構的解決方案; 其次,如何利用 Composite 模式將您的內部層次結構轉換為您想要的 JSON。
第 1 部分:創建繼承權
一種方法是通過將元素划分為 bin 來迭代地創建對象(從包含每個元素的公共復合根對象開始)。 這將形成數據的復合結構。 流程將是:
=
還剩下更多數據:
=
后面還有其他數據:
例如,假設我們正在使用給定的數據集:
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
既是一個數組又是一個值。
請嘗試 Gson 庫並使用 new Gson().toJson(yourmap); 這會將您的地圖轉換為 JSON 格式。
也許您可以通過拆分數字開始處的鍵來解決它,並對子鍵使用 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
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.