1

I have a JSON with this content:

[ {
    "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. I have tried using HashMaps and Maps instead of inner classes, but it doesn't work. Is there a way I can parse this using Gson?

UPDATE:

I have changed lines from MyObject to a Map<String, String> and added some more lines to JSON response

At the moment this is the code I'm using to parse the 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. I think this may be part of the problem

2 Answers 2

2

Use Map<String, String> instead Line[] lines.

(You don't need class Line)

It should work.

Or if your keys are integers Map<Integer, String> will work as well

[Edit]

Your json String represents list of objects: {..},{..},{..}

You need wrap it with [].

So the working json should be:

[
    {
        "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;   
}

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

Sign up to request clarification or add additional context in comments.

3 Comments

I tried it like this public Map<String, String> lines; but my app crashed and gave following exception 09-27 19:31:38.636: E/AndroidRuntime(17729): 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>
before you extract lines validate ots not null and size > 0. Its easy to catch it
Yes I'm doing the same and I seem to have found the problem. sometimes if if there is no value for lines it is returned as a string "" and when there is a value it is return as a Map Object
0

I like Maxim's solution for simplicity and +1 for him. Bur there is also other, little more complex way of doing it. In Lines class you can write keys as _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

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.

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

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" : "". Since you are placing there object (data inside {...}) you can't change your format later to string (which is not object in JSon format).
So if you can change your JSon you should replace "lines" : "" with either

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

3 Comments

I don't really understand this strategy, the numbers 0, 1, etc are not keys as such they can go on to 20. The crashing seems to occur when the value returned for this is ""
@user2611073 could you show code you use to parse your json? Also is posted json string only fragment of json array? If not then you may need to surround your json string with [ and ] since (if I am not mistaken) to parse json string is must be either one object or array of objects.
@user2611073 I updated my answer with additional informations and changed earlier code a little.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.