如何反序列化可能是字符串,对象或列表的json / gson

时间:2012-11-08 04:17:19

标签: java android json gson

我有以下json

"notes": {"note": [
         {
             "content": "Having wisdom teeth removed.",
             "from": "employee"
         },
         {
             "content": "Get well soon",
             "from": "manager"
         }
     ]},

问题在于价值也是

 "notes": "",

"notes": {"note": {
            "content": "This is a test note.",
            "from": "employee"
        }},

并将其存储在这些

public  class Notes
{
    @SerializedName ("note")
    public List<Note> note;
}
public  class Note
{
    @SerializedName ("content")
    public String content;
    @SerializedName ("from")
    public String from;
}

我相信我解决了不是数组而是通过这样做成为单个对象的问题

public class Json {
    private static Gson gson;

    private static class MyNoteClassTypeAdapter implements JsonDeserializer<List<RequestsDTO.Note>> {
        public List<RequestsDTO.Note> deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext ctx) {
            List<RequestsDTO.Note> vals = new ArrayList<RequestsDTO.Note>();
            if (json.isJsonArray()) {
                for (JsonElement e : json.getAsJsonArray()) {
                    vals.add((RequestsDTO.Note) ctx.deserialize(e, RequestsDTO.Note.class));
                }
            } else if (json.isJsonObject()) {
                vals.add((RequestsDTO.Note) ctx.deserialize(json,RequestsDTO.Note.class));
            } else {
                throw new RuntimeException("Unexpected JSON type: " + json.getClass());
            }
            return vals;
        }
    }

    public static Gson getGson()
    {
        if (gson == null)
        {
            Type ListType = new TypeToken<List<RequestsDTO.Note>>() {}.getType();
            GsonBuilder builder = new GsonBuilder();
            builder.registerTypeAdapter(DateTime.class, new DateTimeSerializer());
            builder.registerTypeAdapter(ListType, new MyNoteClassTypeAdapter());
            gson = builder.create();
        }
        return gson;
    }
}

现在,当整个事情以字符串形式返回时,我被困住了......

3 个答案:

答案 0 :(得分:1)

我们的想法是首先尝试将"note"字段(来自"notes" JSONObject)作为JSONArray,如果它引发异常则意味着没有{{1} } "note"进入JSONArray "notes",这意味着JSONObject"note"。我们可以在JSONObject字段为note时找出相同的情况。

String

在我的示例代码中,另一个try { //String jsonString="{\"notes\": {\"note\": [{\"content\": \"Having wisdom teeth removed.\",\"from\": \"employee\" }, {\"content\": \"Get well soon\", \"from\": \"manager\"} ] }}"; //String jsonString="{\"notes\": { \"note\": {\"content\": \"This is a test note.\",\"from\": \"employee\"}}}"; String jsonString="{\"notes\": { \"note\": \"\"}}"; JSONObject jsonObject=new JSONObject(jsonString); JSONObject jsonObjectNotes=jsonObject.getJSONObject("notes"); try{ JSONArray jsonArrayNote=jsonObjectNotes.getJSONArray("note"); for (int i = 0; i < jsonArrayNote.length(); i++) { JSONObject jsonObject2= jsonArrayNote.getJSONObject(i); String stringContent=jsonObject2.getString( "content"); String stringFrom= jsonObject2.getString( "from"); Log.e(getClass().getName(), "content="+stringContent +"; from="+stringFrom); } } catch(JSONException e){ //that means that jsonObjectNotes has no jsonArray with name "notes" and "notes" is jsonObject try{ JSONObject jsonObject3=jsonObjectNotes.getJSONObject("note"); String stringContent=(String) jsonObject3.get( "content"); String stringFrom=(String) jsonObject3.get( "from"); Log.e(getClass().getName(), "content="+stringContent +"; from="+stringFrom); } catch(JSONException ex){ //that means that jsonObjectNotes has no jsonObject with name "notes" and "notes" is empty String String stringNote=jsonObjectNotes.getString("note") ; Log.e(getClass().getName(), "note is string ="+ stringNote); } } } catch (JSONException e) { e.printStackTrace(); } 操作也可以抛出jsonExceptions但我认为你明白了。

答案 1 :(得分:1)

请参阅下面的代码片段,使用Gson库反序列化您的json,无异常。

String jsonStr = "your json string ";

Gson gson = new Gson();
JsonObject jsonObj = gson.fromJson (jsonStr, JsonElement.class).getAsJsonObject();

JsonElement elem = jsonObj.get("note");

if(elem.isJsonArray()) { //**Array**
    List<Note> notelist = gson.fromJson(elem.toString(), new TypeToken<List<Note>>(){}.getType());
} else if(elem.isJsonObject()) { //**Object**
    Note note = gson.fromJson(elem.toString(), Note.class);
} else {  //**String**
    String note = elem.toString();
}

答案 2 :(得分:0)

看一下Genson图书馆http://code.google.com/p/genson/。 如果您的类是内部类,则将它们设置为静态。 以下代码可以解决您的问题。

Genson genson = new Genson.Builder().withDeserializerFactory(new NotesDeserializerFactory()).create();
Notes notes = genson.deserialize(in, Notes.class);

// Define a factory so you can delegate the deserialization to existing mechanisms for lists and beans
class NotesDeserializerFactory implements Factory<Deserializer<Notes>> {

    @Override
    public Deserializer<Notes> create(Type type, Genson genson) {
        Converter<List<Note>> noteListConverter = genson.provideConverter(new GenericType<List<Note>>() {}.getType());
        Converter<Note> noteConverter = genson.provideConverter(Note.class);
        return new NotesDeserializer(noteListConverter, noteConverter);
    }

}

// define an implementation for you Notes class so you can handle the different cases
class NotesDeserializer implements Deserializer<Notes> {
    private final Converter<List<Note>> noteListConverter;
    private final Converter<Note> noteConverter;

    public NotesDeserializer(Converter<List<Note>> noteListConverter,
            Converter<Note> noteConverter) {
        this.noteListConverter = noteListConverter;
        this.noteConverter = noteConverter;
    }

    @Override
    public Notes deserialize(ObjectReader reader, Context ctx) throws TransformationException,
            IOException {
        Notes notes = new Notes();
        if (reader.getValueType() == ValueType.ARRAY) notes.note = noteListConverter.deserialize(reader, ctx);
        else if (reader.getValueType() == ValueType.OBJECT) notes.note = Arrays.asList(noteConverter.deserialize(reader, ctx));
        else { // it is a litteral (string, numeric, boolean, null)
            notes.note = new ArrayList<Note>();
        }
        return notes;
    }
}