Reputation: 77
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
Upvotes: 1
Views: 6985
Reputation: 77910
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
Upvotes: 2
Reputation: 124275
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
"lines" : {}
.Upvotes: 0