如何将平面映射转换为复杂的JSONObject? [英] How to transform a flat map to complex JSONObject?

查看:86
本文介绍了如何将平面映射转换为复杂的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(); 
              }
              

              如果遵循上述内容,我们可能会使用该接口的三个实现:ArrayCompositeObjectCompositeValueLeaf.

              If following the above, we would likely have three implementations of this interface: ArrayComposite, ObjectComposite, and ValueLeaf.

              在根元素上调用toJsonObject()将为您提供完整的JsonObject.下面是上述示例的结构化表示形式(请注意y数组中添加的间隙;这需要在数组组合的toJsonObject()调用中处理):

              Calling toJsonObject() on your root element will give you your complete JsonObject. A textural representation of that for the above example is below (notice the added gap in the y array; this needs to be handled in the toJsonObject() 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆