I need to deserialize a Json file that has an array. I know how to deserialize it so that I get a List object, but in the framework I am using a custom list object that does not implement the Java List interface. My question is, how do I write a deserializer for my custom list object?
EDIT: I want the deserializer to be universal, meaning that I want it ot work for every kind of list, like CustomList<Integer>, CustomList<String>, CustomList<CustomModel> not just a specific kind of list since it would be annoying to make deserializer for every kind I use.
This is what I came up with:
class CustomListConverter implements JsonDeserializer<CustomList<?>> {
public CustomList deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext ctx) {
Type valueType = ((ParameterizedType) typeOfT).getActualTypeArguments()[0];
CustomList<Object> list = new CustomList<Object>();
for (JsonElement item : json.getAsJsonArray()) {
list.add(ctx.deserialize(item, valueType));
}
return list;
}
}
Register it like this:
Gson gson = new GsonBuilder()
.registerTypeAdapter(CustomList.class, new CustomListConverter())
.create();
Related
I need help with the gson library, basically i have to de-serialize a wrapper class defined like this:
static class WrapperClass {
public int value;
private final String otherData;
public WrapperClass(String otherData) {
this.otherData = otherData;
}
}
The class that I have to "jsonize" has fields like this:
private final WrapperClass wrappedData = new WrapperClass("other data");
The serializer of the wrapper class is really simple:
#Override
public JsonElement serialize(WrapperClass src, Type typeOfSrc, JsonSerializationContext context) {
return context.serialize(src.value);
}
The problem is the de-serialization side, I should not re-instantiate the WrapperClass object because it's already there by default, i have only to de-serialize it's value, it's possible to this with the gson library?
So, what you want to do: "read" the content of some JSON string and "overlay" existing objects with that.
I am not aware of a built-in way to do that. Beyond that: doing something of this complexity under the covers sounds like the wrong approach, too.
Thus, my recommendation: clearly separate those responsibilities. Meaning: instead of of creating a (almost counter-intuitive) solution that merges JSON data "into" existing objects: do that explicitly, it step by step. Like:
read the JSON data and de-serialize into one or more objects
then have an another special component "update" your "old" objects with the information found in the de-serialized objects
I want to serialize a java map into json and I can definitely use either jackson or gson.
But when I serialize, I want to ignore specify key. Is it possible?
Map is . I don't have/want my Map backed by a POJO because the keys are very generic and could be anything. I understand if it was a POJO, we can use Ignore annotation to achieve.
You can create a custom class that extends HashMap:
public class MyMap extends HashMap<String, Object> {
}
and then register a custom serializer, like:
public class MyMapSerializer extends JsonSerializer<MyMap> {
#Override
public JsonElement serialize(MyMap arg0, Type arg1, JsonSerializationContext arg2) {
JsonObject result = new JsonObject();
for (String k : arg0.keySet()) {
if (whatever your condition is) {
result.add(k, arg0.get(k));
}
}
return result;
}
}
Then when you create the Gson object you need to initialize it by passing an instance of the serializer:
Gson gson = new GsonBuilder().registerTypeAdapter(MyMap.class, new MyMapSerializer()).create();
I have overriden an Integer Adapter in GSON to parse my JSON. Reason for doing this is that the GSON method parseJson simply throws the JsonSyntaxException if anything goes wrong. To avoid sending a generic exception I created this adapter. I want the adapter to throw an exception along with the name of the Key. Problem is that I can not get the key name in the overriden method deserialize of JsonDeserializer[T]
Code snippet
val integerAdapter = new JsonDeserializer[Integer] {
override def deserialize(json: JsonElement, typeOfT: Type, context: JsonDeserializationContext): Integer = {
Try(json.getAsInt) //JsonElement object has only the value
match {
case Success(value) => value
case Failure(ex) => throw new IllegalArgumentException(ex) // here i want the name of the key to be thrown in the exception and manage accordingly
}
}
}
Json:{
"supplierId":"21312",
"isClose":false,
"currency":"USD",
"statusKey":1001,
"statusValue":"Opened ",
"statusDateTime":"2014-03-10T18:46:40.000Z",
"productKey":2001,
"productValue":"Trip Cancellation",
"TypeKey":3001,
"TypeValue":"Trip Cancellation",
"SubmitChannelKey":4001,
"SubmitChannelValue":"Web asdsad",
"tripNumber":"01239231912",
"ExpiryDateTime":"2014-03-10T18:46:40.000Z",
"numberOfants":4,
"AmountReserved":901232,
"AmountRequested":91232
}
Any leads on this?
Your adapter is a deserializer for the Integer type which is a wrapper for a primitive. Because it's not a regular object, Gson will not associate a key with it.
Why not implement a deserializer for the whole JSON object to have access to all keys?
class MyObject {
private Integer supplierId;
private boolean isClose;
// TODO: the other fields in the JSON string
}
class MyObjectDeserializer implements JsonDeserializer<MyObject> {
public MyObject deserialize(JsonElement jsonElement, Type type,
JsonDeserializationContext jsonDeserializationContext) throws JsonParseException {
// TODO: construct a new MyObject instance
}
}
I need to convert a java object (called org) to json format.
The object (DTO ) is a bit complex, because it contains a list of objects of the same class and which in turn can also contain more objects of the same class ( built recursively). When I passing the object to gson.toJsonTree method it seems to fail (there isnt any error), but it seems that the method does not like complex objects). If I set to null the list of objects of the first object everything works fine. I can not modify the class, only the method that makes json.
JsonElement jsonUO = null;
jsonUO = gson.toJsonTree(org,OrgDTO.class);
jsonObject.add("ORG", jsonUO)
public class OrgDTO implements Serializable{
private String id;
......
private List sucesores;
public OrgDTO(){
this.sucesores = new ArrayList();
}
.....
}
It might be a little bit late for the questioner, however I share my answer in case someone else face similar issue:
You'll need to create a helper class that does the json serialization. It should implement the JsonDeserializer:
public class OrgDTOJsonSerializer implements JsonDeserializer<OrgDTO> {
#Override
public JsonElement serialize(OrgDTO src, Type type, JsonSerializationContext jsc) {
JsonObject jsonObject = new JsonObject();
jsonObject.addProperty("id", src.getId());
/// Build the array of sucesores (whatever it means!)
JsonArray sucesoresArray = new JsonArray();
for (final OrgDTO obj: src.getSucesores()) {
JsonObject succJsonObj = serialize(obj, type, jsc);
sucesoresArray.add(succJsonObj);
}
jsonObject.add("sucesores", sucesoresArray);
return jsonObject;
}
}
Then you'll need to register it in gson before attempting to serialize any object of that type:
GsonBuilder gsonBuilder = new GsonBuilder();
gsonBuilder.registerTypeAdapter(OrgDTO.class, new OrgDTOJsonSerializer());
when deserializing a json into a class Foo{int id; List<String> items; List<Long> dates;} How could I auto initialize fields that are null after deserialization. Is there such a possiblity with Gson lib?
ex:
Foo foo = new Gson().fromJson("{\"id\":\"test\", \"items\":[1234, 1235, 1336]}", Foo.class)
foo.dates.size(); -> 0 and not null pointerException
I know I could do if (foo.attr == null) foo.attr = ...
but I'm looking for more generic code, without knowledge of Foo class
thx
edit: sorry just putting Getters in Foo is enough
closed
You need to create your custom deserializer.
Assuming your class is called MyAwesomeClass, you implement something like
MyAwesomeClassDeserializer implements JsonDeserializer<MyAwesomeClass> {
#Override
public MyAwesomeClass deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext ctx) throws JsonParseException
{
// TODO: Do your null-magic here
}
and register it with GSON, like this:
Gson gson = new GsonBuilder()
.registerTypeAdapter(MyAwesomeClass.class, new MyAwesomeClassDeserializer())
.create();
Now, you just call a fromJson(String, TypeToken) method, to get your deserialized object.
MyAweSomeClass instance = gson.fromJson(json, new TypeToken<MyAwesomeClass>(){}.getType());