简体   繁体   English

使用Gson解析无键的嵌套JSON对象

[英]Parsing nested JSON objects without keys using Gson

I have a JSON with this content: 我有一个包含以下内容的JSON:

[ {
    "lines" : {
        "0" : "Hammersmith & City",
        "1" : "Circle"
    },
    "id" : "233",
    "name" : "Shepherd's Bush Market"
}, {
    "lines" :"",
    "id" : "233",
    "name" : "Shepherd's Bush Market"
}, {
    "lines" : {
        "0" : "Hammersmith & City",
        "1" : "Circle"
    },
    "id" : "233",
    "name" : "Shepherd's Bush Market"
},
, {
    "lines" : "",
    "id" : "233",
    "name" : "Shepherd's Bush Market"
  }]

Normally, I could create an object like this 通常,我可以创建一个这样的对象

public class MyObject {

    public String id;  
    public String name;
    public Line[] lines;

    public class Line {
        public String key;
        public String value;
    }
}

And the Gson serializer would handle the parsing, but in this case lines doesn't have any keys/ids. Gson序列化程序将处理解析,但是在这种情况下, lines没有任何键/ ID。 I have tried using HashMaps and Maps instead of inner classes, but it doesn't work. 我尝试使用HashMapsMaps而不是内部类,但是它不起作用。 Is there a way I can parse this using Gson? 有什么方法可以使用Gson解析吗?

UPDATE: 更新:

I have changed lines from MyObject to a Map<String, String> and added some more lines to JSON response 我已将linesMyObject更改为Map<String, String> ,并向JSON响应中添加了更多行

At the moment this is the code I'm using to parse the JSON 目前,这是我用来解析JSON的代码

Type listType = new TypeToken<List<MyObject>>(){}.getType();
List<MyObject> data = getGson().fromJson(str, listType);

Caused by: com.google.gson.JsonParseException: The JsonDeserializer MapTypeAdapter    failed to deserialize json object "" given the type java.util.Map<java.lang.String, java.lang.String>

After looking through the entire JSON response, it seems that lines is returned as a empty String ("") when it's not available and as a map when it is. 浏览完整个JSON响应后,似乎lines不可用时以空String (“”)的形式返回,而当行不存在时以地图的形式返回。 I think this may be part of the problem 我认为这可能是问题的一部分

Use Map<String, String> instead Line[] lines . 使用Map<String, String>代替Line[] lines

(You don't need class Line ) (您不需要Class Line

It should work. 它应该工作。

Or if your keys are integers Map<Integer, String> will work as well 或者,如果您的键是整数Map<Integer, String>也可以工作

[Edit] [编辑]

Your json String represents list of objects: {..},{..},{..} 您的json字符串表示对象列表: {..},{..},{..}

You need wrap it with [] . 您需要使用[]包装。

So the working json should be: 因此,工作的json应该是:

[
    {
        "lines": {
            "0": "Hammersmith & City",
            "1": "Circle"
        },
        "id": "233",
        "name": "Shepherd's Bush Market"
    },
    {
        "lines": {
            "0": "Hammersmith & City",
            "1": "Circle"
        },
        "id": "233",
        "name": "Shepherd's Bush Market"
    },
    {
        "lines": {
            "0": "Hammersmith & City",
            "1": "Circle"
        },
        "id": "233",
        "name": "Shepherd's Bush Market"
    }
]

MyObject 为MyObject

public class MyObject {
 public String id;

 public String name;

 public Map<String,String> lines;   
}

main method 主要方法

    Gson gson = new Gson();
    Type type = new TypeToken<List<MyObject>>(){}.getType();
    List<MyObject > objList = gson.fromJson(str, type);


    assert(objList != null);  // validate not null

    for(MyObject obj : objList){

        System.out.println("id=" + obj.id + "; name=" + obj.name);
    }

Output: 输出:

id=233; name=Shepherd's Bush Market
id=233; name=Shepherd's Bush Market
id=233; name=Shepherd's Bush Market

in the loop you can extract Map as well 在循环中,您也可以提取Map

I like Maxim's solution for simplicity and +1 for him. 我喜欢Maxim的简单解决方案,并喜欢+1。 Bur there is also other, little more complex way of doing it. Bur还有另外一种更复杂的方法。 In Lines class you can write keys as _0 , _1 Lines类中,您可以将键写为_0_1

class Lines {
    private String _0;
    private String _1;
    //@Override
    //public String toString() {
    //    return "Lines [0=" + _0 + ", 1=" + _1 + "]";
    //}

}

and use it in MyObject like 并像这样在MyObject使用它

class MyObject {

    private Lines lines;
    private String id;
    private String name;

    //@Override
    //public String toString() {
    //    return "Example [lines=" + lines + ", id=" + id + ", name=" + name + "]";
    //}
}

After that you will have to create FieldNamingStrategy that would remove _ from numeric key. 此后,您将必须创建将从数字键中删除_ FieldNamingStrategy

class MyNameStrategy implements FieldNamingStrategy {

    static Pattern numericPattern = Pattern.compile("_\\d+");

    @Override
    public String translateName(Field f) {
        if (numericPattern.matcher(f.getName()).matches()){
            return f.getName().substring(1);
        }else{
            return f.getName();
        }
    }
}

To use this strategy you need to create Gson via GsonBuilder 要使用此策略,您需要通过GsonBuilder创建Gson

Gson gson = new GsonBuilder().setFieldNamingStrategy(
        new MyNameStrategy()).create();
//...
MyObject[] arr = gson.fromJson(jsonString, MyObject[].class);
System.out.println(Arrays.toString(arr));

Also you are right that your JSon have problem in "lines" : "" . 您也很正确,您的JSon在"lines" : ""有问题。 Since you are placing there object (data inside {...} ) you can't change your format later to string (which is not object in JSon format). 由于您将object{...}内的数据)放置在那里,因此以后无法将格式更改为string (不是JSon格式的对象)。
So if you can change your JSon you should replace "lines" : "" with either 因此,如果您可以更改JSon,则应将"lines" : ""替换为

  • "lines" : null
  • or "lines" : {} . "lines" : {}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM