2015-06-09 14 views
8

Ho una struttura JSON che ho incollato qui sotto. Mi piacerebbe deserializzare il json in un POJO java usando Gson che è piuttosto diretto, tranne che voglio mantenere uno dei campi, data, come un tipo di stringa invece di un oggetto nidificato.Come posso deserializzare un oggetto JSON ma mantenere un campo specifico come stringa invece di un oggetto nidificato?

struttura JSON

{ 
    "created_on": "2015-06-04T16:12:04-0700", 
    "modified_on": "2015-06-04T16:12:09-0700", 
    "identifier": "sample", 
    "name": "some name", 
    "summary": "some summary", 
    "data": { 
    "$type": "a_type", 
    "some_other_stuff": { 
     "more_stuff": "lorem ipsum" 
    }, 
    "type2": { 
     "$type": "another_type", 
     "other_stuff": { 
      "event_more_stuff": "lorem ipsum" 
     } 
    } 
    } 
} 

mio POJO sarebbe quindi simile a questa:

public class Sample { 
    private String identifier; // "sample" 
    private String created_on; // "2015-06-04T16:12:04-0700" 
    private String modified_on; // "2015-06-04T16:12:09-0700" 
    private String name; // "some name" 
    private String summary; // "some summary" 
    private String data; // "{ \"$type\": ... }" 

    // getters and setters 
} 

Il campo data deve rimanere come una stringa in formato JSON.

Ho provato a implementare un numero personalizzato TypeAdapter e a leggere il campo come stringa, ma non riesce con Expected a string but was BEGIN_OBJECT.

Inoltre, mi piacerebbe che la struttura venga mantenuta anche sulla serializzazione, così posso serializzare il POJO sulla struttura JSON originale.

Modifica personalizzato TypeAdapter:

public class SampleTypeAdapter extends TypeAdapter<Sample> { 
@Override 
public void write(JsonWriter out, Sample sample) throws IOException { 
    out.beginObject(); 

    out.name("identifier").value(sample.getIdentifier()); 
    out.name("name").value(sample.getName()); 
    out.name("data").value(sample.getData()); 
    out.name("summary").value(sample.getSummary()); 
    out.name("modified_on").value(sample.getModifiedOn()); 
    out.name("created_on").value(sample.getCreatedOn()); 

    out.endObject(); 
} 

@Override 
public Sample read(JsonReader in) throws IOException { 
    final Sample sample = new Sample(); 

    in.beginObject(); 
    while (in.hasNext()) { 
     String nextName = in.nextName(); 
     switch (nextName) { 
      case "identifier": 
       sample.setIdentifier(in.nextString()); 
       break; 
      case "name": 
       sample.setName(in.nextString()); 
       break; 
      case "data": 
       sample.setData(in.nextString()); // <-- fails here 
       break; 
      case "summary": 
       sample.setSummary(in.nextString()); 
       break; 
      case "modified_on": 
       sample.setModifiedOn(in.nextString()); 
       break; 
      case "created_on": 
       sample.setCreatedOn(in.nextString()); 
       break; 
      default: 
       in.skipValue(); 
       break; 
     } 
    } 
    in.endObject(); 

    return sample; 
} 
} 
+0

Potresti pubblicare il TypeAdapter personalizzato? – Cata

risposta

5

si potrebbe creare un costume JsonDeserializer come questo:

public class SampleGSONParserAdapter implements 
     JsonDeserializer<Sample> { 

    @Override 
    public Sample deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { 

     Sample sample = new Sample(); 
     JsonObject sampleJsonObject = json.getAsJsonObject(); 

     sample.setName(sampleJsonObject.get("name").getAsString()); 

     // do the other parsing stuff here.. 

     // getting the data object as a string 
     sample.setJsonString(sampleJsonObject.get("data").toString()); 

     return sample; 
    } 

} 

e si utilizza in questo modo:

GsonBuilder gsonBuilder = new GsonBuilder(); 
     gsonBuilder.registerTypeAdapter(Sample.class, new SampleGSONParserAdapter()); 
Gson gson = gsonBuilder.create(); 

La parte negativa è che non è più veloce come quello che hai scritto, ma almeno puoi fare un parsing personalizzato come questo.

0

Utilizzare questa classe personalizzata, trovare gli strumenti necessari:

public class JsonParser 
{ 

    public static <T> List<T> parseList(String json_text, String json_path, Class<T> c) 
    { 
     Gson gson = new Gson(); 
     try 
     { 
      List<T> json_list = new ArrayList<>(); 
      List<Object> nodes = JsonPath.read(json_text, json_path); 

      for(Object node : nodes) 
      { 
       json_list.add(gson.fromJson(node.toString(), c)); 
      } 
      return (json_list); 
     } 
     catch(Exception e) 
     { 
      return (new ArrayList<>()); 
     } 
    } 
    public static <T> T parseObject(String json_text, Class<T> c) 
    { 
     return (new Gson()).fromJson(json_text, c); 
    } 

    public static <T> T getItemAtPosition (String json_text, String json_path) 
    { 
     try 
     { 
      return (JsonPath.read(json_text, json_path)); 
     } 
     catch(Exception e) 
     { 
      return (null); 
     } 
    } 
} 

montaggio finale:

Dal momento che ciò che si vuole è solo una parte della vostra JSON per rimanere una stringa JSONed, di tutto ciò di cui potresti aver bisogno (il che significa solo JsonPath):

String myData = JsonParser.getItemAtPosition(response,"$.data[*]").toString(); 
+0

Forse mi manca qualcosa, ma non vedo come questo mantenga il campo 'data' come una variabile stringa che era il nocciolo della domanda. Inoltre, il tuo metodo di analisi di una lista potrebbe essere semplificato su una singola riga usando un 'TypeToken'. – howettl

+0

l'analisi è per chiarimenti, mancati sulla parte dati, modifica – TommySM

+0

Scusa ma questo non risponde alla mia domanda. L'analisi di un POJO non è la sfida. – howettl

Problemi correlati