简体   繁体   中英

Problem deserializing Bugzilla JSON using Google's Gson

I'm hitting a problem in JSON I'm getting back from a Bugzilla server because it sometimes returns "text" : {} and sometimes "text" : "blah blah blah". Bugzilla returns the former if no description was given for a bug. I'm mystified why it doesn't come back as the much more sensible "text" : "" but it does and that's it.

If I have a String named text in the target object for Gson, it objects when it sees the {} case because it says that's an object and not a String:

Exception in thread "main" com.google.gson.JsonParseException: The 
JsonDeserializer StringTypeAdapter failed to deserialized json object {} given 
the type class java.lang.String

Any suggestions on how I can make Gson parse this?

Gson requires custom deserialization for the situation in the original question. Following is one such example.

input.json:

[
  {
    "text":"some text"
  },
  {
    "text":{}
  }
]

Foo.java:

import java.io.FileReader;
import java.lang.reflect.Type;

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonDeserializationContext;
import com.google.gson.JsonDeserializer;
import com.google.gson.JsonElement;
import com.google.gson.JsonParseException;

public class Foo
{
  public static void main(String[] args) throws Exception
  {
    GsonBuilder gsonBuilder = new GsonBuilder();
    gsonBuilder.registerTypeAdapter(String.class, new StringDeserializer());
    Gson gson = gsonBuilder.create();
    Thing[] things = gson.fromJson(new FileReader("input.json"), Thing[].class);
    System.out.println(gson.toJson(things));
  }
}

class Thing
{
  String text;
}

class StringDeserializer implements JsonDeserializer<String>
{
  @Override
  public String deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
      throws JsonParseException
  {
    if (json.isJsonPrimitive()) return json.getAsString();
    return "";
  }
}

Output:

[{"text":"some text"},{"text":""}]

Using instead a custom deserializer for the Thing.class type would of course be possible. This would have the benefit of not adding additional processing for every String , but then you'd be stuck with "manual" processing all of the other attributes of Thing .

Try declaring the text field to be an Object . Then do something like:

public String getTextAsString() {
    if (text instanceof String) {
        return (String) text;
    else {
        return null;
    }
}

You should report this as a bug to the Bugzilla project. There's no good reason for this behavior.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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