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

时间:2013-09-27 18:06:14

标签: java android json parsing gson

我有一个包含此内容的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"
  }]

通常,我可以创建一个这样的对象

public class MyObject {

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

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

Gson序列化程序将处理解析,但在这种情况下lines没有任何键/ ID。我尝试使用HashMapsMaps而不是内部类,但它不起作用。有没有办法可以使用Gson解析它?

更新:

我已将linesMyObject更改为Map<String, String>,并为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>

查看整个JSON响应后,似乎lines在空闲String(“”)不可用时返回,如果是,则返回地图。我认为这可能是问题的一部分

2 个答案:

答案 0 :(得分:2)

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

(您不需要课程Line

它应该有用。

或者,如果您的密钥是整数,Map<Integer, String>也可以正常使用

<强> [编辑]

您的json String表示对象列表:{..},{..},{..}

您需要使用[]包装它。

所以工作的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

public class MyObject {
 public String id;

 public String name;

 public Map<String,String> lines;   
}

主要方法

    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);
    }

输出:

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

在循环中,您也可以提取Map

答案 1 :(得分:0)

我喜欢Maxim的简化解决方案和+1。 Bur还有其他更简单的方法。在Lines课程中,您可以将密钥写为_0_1

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

}

并在MyObject中使用

class MyObject {

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

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

之后,您必须创建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();
        }
    }
}

要使用此策略,您需要通过Gson

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

你是对的,你的JSon在"lines" : ""中有问题。由于您放置了object{...}内的数据),因此您无法在以后将格式更改为string(这不是JSon格式的对象)。
因此,如果您可以更改JSon,则应将"lines" : ""替换为

  • "lines" : null
  • "lines" : {}