The code works and deserializes the JSON string
{"d": [{"d1": "D1"}, {"d2": "D2"}]}
to the dto
object, of type Dto
, using GSON and a custom TypeAdapter<Dto>
. However, the DtoAdapter
class seems a bit complicated to me. Is there a better implementation for the DtoAdapter
? And is there a better way to custom deserialize the JSON string using GSON to get the same result?
public class Main {
public static void main(String[] args) {
GsonBuilder builder = new GsonBuilder();
builder.registerTypeAdapter(Dto.class, new DtoAdapter());
Gson gson = builder.create();
String json = "{\"d\": [{\"d1\": \"D1\"}, {\"d2\": \"D2\"}]}";
Dto dto = gson.fromJson(json, Dto.class);
System.out.println(dto); // Dto(items=[Dto.Item(name=D1 custom case 1), Dto.Item(name=D2 custom case 2)])
}
}
class DtoAdapter extends TypeAdapter<Dto> {
@Override
public Dto read(JsonReader reader) throws IOException {
Dto dto = new Dto();
reader.beginObject(); // Start JSON string {...}
while (reader.hasNext()) {
switch (reader.nextName()) {
case "d":
reader.beginArray(); // Start Array {"d": [...]}
while (reader.hasNext()) {
reader.beginObject(); // Start Object in Array {"d": [{...}, ]}
Dto.Item item = new Dto.Item();
switch (reader.nextName()) {
case "d1":
item.setName(reader.nextString() " custom case 1");
dto.getItems().add(item);
break;
case "d2":
item.setName(reader.nextString() " custom case 2");
dto.getItems().add(item);
break;
}
reader.endObject(); // End Object in Array
}
reader.endArray(); // End Array
break;
}
}
reader.endObject(); // End JSON string
return dto;
}
@Override
public void write(JsonWriter writer, Dto dto) throws IOException {
// Serialize
}
}
@Data
public class Dto {
List<Item> items = new ArrayList<>();
@Data
public static class Item {
private String name;
}
}
CodePudding user response:
You can write custom deserilizer like this:
import com.google.gson.JsonArray;
import com.google.gson.JsonDeserializationContext;
import com.google.gson.JsonDeserializer;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParseException;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
public class CustomDeserilizer implements JsonDeserializer<Dto> {
@Override
public Dto deserialize(JsonElement jsonElement, Type type, JsonDeserializationContext jsonDeserializationContext) throws JsonParseException {
JsonObject jobject = jsonElement.getAsJsonObject();
JsonArray jsonArray = jobject.getAsJsonArray("d");
Dto dto = new Dto();
List<Dto.Item> items = new ArrayList<>();
for (int i = 0; i < jsonArray.size(); i ) {
Dto.Item item = new Dto.Item();
JsonObject object = jsonArray.get(i).getAsJsonObject();
if(Objects.nonNull(object.get("d1"))){
item.setName(object.get("d1").getAsString() " custom case 1");
}
if(Objects.nonNull(object.get("d2"))){
item.setName(object.get("d2").getAsString() " custom case 2");
}
items.add(item);
}
dto.setItems(items);
return dto;
}
}
And if you test it using below code:
GsonBuilder gsonBuilder = new GsonBuilder();
String json = "{\"d\": [{\"d1\": \"D1\"}, {\"d2\": \"D2\"}]}";
gsonBuilder.registerTypeAdapter(Dto.class, new CustomDeserilizer());
Gson customGson = gsonBuilder.create();
Dto customObject = customGson.fromJson(json, Dto.class);
System.out.println(customObject);
You should see output like this:
Dto{items=[Item{name='D1 custom case 1'}, Item{name='D2 custom case 2'}]}
CodePudding user response:
Seems you could create a DTO property with an alternate name for your list item.
public class D {
@SerializedName(value = "d1", alternate = "d2")
@Expose
private String d1;
public String getD1() {
return d1;
}
public void setD1(String d1) {
this.d1 = d1;
}
}