Как я могу десериализовать объект JSON, но сохранить конкретное поле как String вместо вложенного объекта?

У меня есть структура json, которую я вставил ниже. Я хотел бы десериализовать json в java POJO, используя Gson который довольно прямолинейный, за исключением того, что я хочу сохранить одно из полей, data , как тип String, а не вложенный объект.

Структура 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" } } } } 

Тогда мой POJO будет выглядеть так:

 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 } 

Поле data должно оставаться в виде строки в формате JSON.

Я пробовал реализовать пользовательский TypeAdapter и читал поле как String, но он не Expected a string but was BEGIN_OBJECT с Expected a string but was BEGIN_OBJECT .

Также обратите внимание, что я хотел бы, чтобы структура также поддерживалась при сериализации, поэтому я могу сериализовать POJO обратно в исходную структуру JSON.

Редактировать пользовательский 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; } } 

Solutions Collecting From Web of "Как я могу десериализовать объект JSON, но сохранить конкретное поле как String вместо вложенного объекта?"

Вы можете создать настраиваемый JsonDeserializer следующим образом:

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

И вы используете его вот так:

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

Плохая часть заключается в том, что это не так быстро, как тот, который вы написали, но по крайней мере вы можете выполнять индивидуальный синтаксический разбор, как этот.

Используйте этот пользовательский класс, добавьте то, что вам нужно:

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

ЗАКЛЮЧИТЕЛЬНЫЙ РЕДАКТ:

Поскольку то, что вы хотите, является частью вашего JSON, чтобы оставаться JSONed String, из всего этого вам может понадобиться (что означает только JsonPath ):

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