如何读取具有可变数组深度和结构的复杂JSON字符串?

时间:2012-09-01 12:36:46

标签: java json algorithm nested-lists

我有很多JSON数据,这些数据是在嵌套列表中组织的。每个列表都包含其他列表,这些列表可能包含其他列表等。最深的清单包括一对穷人和纬度,例如

  

[[[..... [16.353542354,48.2354242424],[16.46353535,48.2546754646] ....] .....]。

它看起来像这样的图形:

Coord list

我基本上不知道这些列表是如何嵌套的。它们一直不同。接下来的困难部分是我需要从中获取“坐标多边形”。这意味着仅由坐标对组成的列表属于同一个多边形。例如:

  

[...... [[16.23542424,48.2342424242],[16.2423242352354,48.12342534634],[16.35353453535,48.345635353]] ......

这意味着存在由3对坐标组成的多边形(因此3个角)。 我确信这可以通过某种String解析来解决。我想知道这是否可能与基本的JSON.simple(或可能任何其他API)可能性。问题是JSON对它正在解析的数据一无所知。我必须告诉JSON对象是什么,并且必须使用类型转换来获取正确的数据。请参阅这些示例here。现在我需要另一种方式,但我永远不知道数据是什么类型(“它是另一个列表还是数据一对坐标”),因为这些列表非常动态。怎么能以方便的方式完成?我可以用一些“推送和弹出行为”来编写一些字符串解析算法,以逐字符比较JSON字符串,但我想知道是否有更好的方法来做到这一点?

[UPDATE]
我发现这是一种标准化的JSON格式,称为GeoJSON。如果您知道如何阅读数据,那就很清楚了。多边形由多边形组成,多边形可以有多个孔,由Polygon对象中的第二个数组表示。见规格: PolygonMultipolygon

4 个答案:

答案 0 :(得分:2)

  

我基本上不知道这些列表是如何嵌套的

您确切知道这些列表的嵌套程度。在json的顶部,你有:

"type": "Multipolygon"

对我来说,这意味着List<Polygon>。现在,什么是Polygon?嗯,这显然是List<Coordinate>。最后,我们知道Coordinate是一个包含两个元素的列表。

总而言之,我们有List<List<List<double>>>。阵列的深度是已知的。

class Location {
    private double _lat;
    private double _long;

    public Location(double lat, double long) { _lat = lat; _long = long }

    public static Location fromJSONArray(JSONArray json) {
        int n = json.length();
        if(n != 2) throw new IllegalArgumentException('json');

        return new Location(json.getDouble(0), json.getDouble(1));
    }
}
class Polygon : List<Location> {
    public static Polygon fromJSONArray(JSONArray json) {
        int n = json.length();
        Polygon p = new Polygon();
        for(int i = 0; i < n; i++) {
            p.add(Location.fromJSONArray(json.getJSONArray(i)));
        }
        return polygon;
    }
}

private List<Polygon> parseLists(JSONArray nestedList) throws JSONException
{
    List<Polygon> polygons = new ArrayList<Polygon>();
    int n = json.length();
    for(int i = 0; i < n; i++) {
        polygons.add(Polygon.fromJSONArray(json.getJSONArray(i)));
    }
    return polygons;
}

答案 1 :(得分:0)

用什么语言解析JSON。从理论上讲,这个想法可以应用于大多数语言。如果它的javascript你可以使用

  for(var key in myJSONObjectVariable){
       var current = myJSONObjectVariable[key];
       //Have some logic or inner loops taking place on current
  }

根据JSON数据的不可预测性,我认为你可能是对的。然而,字符串解析可能是要走的路

答案 2 :(得分:0)

这里有多个问题,所以我建议您将问题分解为几个步骤。

第1步,你需要以某种方式在你的嵌套中的某个地方找到一个不同的列表。

您没有提到您正在使用的编程语言,因此该问题的答案会有所不同。如果您直接在JavaScript中执行此操作,则访问任何不同的列表是一种简单的数据访问:

geometry.coordinates[0][1]

或作为列表的Java映射(没有错误检查null返回或无效的数组索引,只是一个例子)

geometry.get("coordinates").get(0).get(1)      

如果您使用的是Java或C ++或类似的东西,您可能会发现使用JSON库并将数据转换为适当的语言结构(例如矢量图)会更容易。我不会尝试直接操作JSON字符串。

然后,一旦您能够以适当的语言获取数据内容,第2步将评估您根据规则检索的内容,并确定您检索的数据的类型

答案 3 :(得分:0)

以下代码将使用JSON Java library(可以从here下载jar)以递归方式将任意深度的纬度和经度值提取到resultantArray中:

public void run() throws JSONException
{
    JSONArray nestedList =
        new JSONArray("[" + "[ 1, 2 ]," + "[ [ 1, 2 ], [ 1, 2 ], [ 1, 2 ] ]," + "[ 3, 4 ],"
            + "[ [ [ [ 1, 2 ], [ 2, 3 ], [ 3, 4 ] ], [ 1, 2 ], [ 1, 2 ], [ 1, 2 ] ] ] ]");
    parseLists(nestedList);
}

private void parseLists(JSONArray nestedList) throws JSONException
{
    List<Location> resultantArray = new ArrayList<Location>();
    parseNestedList(nestedList, resultantArray);
    System.out.println(resultantArray.size());
}

private void parseNestedList(JSONArray json, List<Location> resultantArray) throws JSONException
{
    int elementCount = json.length();
    if (elementCount <= 0)
    {
        return;
    }
    if (json.get(0) instanceof JSONArray)
    {
        for (int i = 0; i < elementCount; i++)
        {
            parseNestedList((JSONArray) json.get(i), resultantArray);
        }
    }
    else
    {
        resultantArray.add(new Location(Double.parseDouble(json.get(0).toString()), Double.parseDouble(json
            .get(1)
            .toString())));
    }
}

完成后,您应该运行算法来识别多边形,并将resultantArray中的条目视为点。