3

I have the following json

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

the issue is that the value coud also be

 "notes": "",

or

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

and storing it in these

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

I believe I solved the issue of not being an array but being an single object by doing this

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;
    }
}

And now I am stuck on when the whole thing just comes back as a string....

WIllJBD
  • 6,144
  • 3
  • 34
  • 44
  • have you checked out this question? http://stackoverflow.com/questions/1688099/converting-json-to-java – Nikolay Kuznetsov Nov 08 '12 at 04:23
  • Yes but the issue is that I know how to serialize/deserialize simple jsons using gson, I am trying to figure out how to do this when the object it returns in the json is not set. – WIllJBD Nov 08 '12 at 04:28
  • check this post for answer http://stackoverflow.com/questions/30897857/custom-converter-for-retrofit/30899048?noredirect=1#comment49838588_30899048 – rahul.ramanujam Jun 17 '15 at 18:55

3 Answers3

2

Refer the code snippet below to deserialize your json using Gson library without exceptions.

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();
}
Purushotham
  • 3,770
  • 29
  • 41
1

The idea is try to get "note" field (from "notes" JSONObject) as JSONArray first and if it throws exception that will mean that there is no "note" JSONArray into "notes" JSONObject and that will mean that "note" is JSONObject. The same way we can figure out situation when note field is 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();
    }

In my example code another get operations can also throw jsonExceptions but I think you get the idea.

ashakirov
  • 12,112
  • 6
  • 40
  • 40
  • I sued this concept but with if() blocks using JSONObject.opt to see if there were appropriate values – WIllJBD Nov 09 '12 at 00:33
0

Have a look at Genson library http://code.google.com/p/genson/. If your classes are inner classes make them static. The following code should solve your problem.

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;
    }
}
eugen
  • 5,856
  • 2
  • 29
  • 26