i am attempting to turn a json string into objects with gson.
I have a very simple example below, and it runs, but the resulting answer is empty, ie: my Answer objec
Because your JSON doesn't match your class.
Your JSON right now is an array of objects, each containing an answer
object as a field.
Your JSON the way you have things would need to look like:
String jsonOutput = "[{\"text\":\"text1\"},{\"text\":\"text2\"}]";
Edit to add from comments:
If you can't change the output, you need a "wrapper". Something like:
public class AnswerWrapper {
public Answer answer;
// etc
}
And use an array of those. That is what the JSON will map to. It can't see them as Answer
objects because ... they're not.
One More Edit to Add: Your other option is to write custom deserializers for your classes. I'm a bit mixed on whether you should do this or not, but it will work. The reason I say that is that you have JSON that isn't an array of Answer
objects, but you want it to be. I think I'd be annoyed if I came across this in production code because without understanding what was going on it could be confusing.
With that caveat being said, you can create a custom JsonDeserializer
and use GsonBuilder
:
class AnswerDeserializer implements JsonDeserializer<Answer> {
public Answer deserialize(JsonElement je, Type type,
JsonDeserializationContext jdc)
throws JsonParseException {
return new Answer(je.getAsJsonObject().get("answer")
.getAsJsonObject().get("text").getAsString());
}
}
Then your code would look like:
public static void main(String[] args) throws Exception{
String jsonOutput = "[{\"answer\":{\"text\":\"text1\"}},{\"answer\":{\"text\":\"text2\"}} ]";
GsonBuilder gsonBuilder = new GsonBuilder();
gsonBuilder.registerTypeAdapter(Answer.class, new AnswerDeserializer());
Gson gson = gsonBuilder.create();
Answer[] a = gson.fromJson(jsonOutput, Answer[].class);
for(Answer i:a) {
System.out.println(i.text);
}
}
If it were me, and I had JSON that wasn't what I needed it to be but wanted to use GSON to directly serialize/deserialize I'd create the Answer
class as a wrapper that hid the details:
/**
* Due to how our JSON is being provided we created an inner
* class.
**/
public class Answer {
private RealAnswer answer;
private class RealAnswer {
public String text;
}
...
}
With the public getters/setters for Answer
accessing the private RealAnswer
. It just seems way cleaner and easier to understand for the next guy.