Parsing polymorphic object with objectmapper - java

I am trying to parse a polymorphic object (it is from the Strava api) with a jackson object mapper. The object looks like this:
[
{
"type": "latlng",
"data": [
[ 38.603734, -122.864112 ],
[ 38.608798, -122.867714 ],
... omitted for brevity ...
[ 38.611205, -122.870848 ],
[ 38.603579, -122.863891 ]
],
"series_type": "distance",
"original_size": 512,
"resolution": "low"
},
{
"type": "distance",
"data": [
0.0,
1305.8,
... omitted for brevity ...
128136.6,
129444.1
],
"series_type": "distance",
"original_size": 512,
"resolution": "low"
}
]
So based on the type the field data has a different object in it. In most cases it is an array of floats. In the case of the "latlng", there is an array of float[], so it is a float[][] (I would think).
I create an object that represents this data structure, with a deserializer. It looks like this:
public class StravaStream {
#JsonProperty("type")
private String type;
public String getType() {
return type;
}
public static class StravaStream1D extends StravaStream {
#JsonProperty("data")
private float[] data;
public StravaStream1D() {
}
public float[] getData() {
return data;
}
}
public static class StravaStream2D extends StravaStream {
#JsonProperty("data")
private float[][] data;
public StravaStream2D() {
}
public float[][] getData() {
return data;
}
}
public StravaStream() {
}
public static class StravaStreamDeserializer extends StdDeserializer<StravaStream> {
public StravaStreamDeserializer() {
super(StravaStream.class);
}
#Override
public StravaStream deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException {
Class<? extends StravaStream> variantStravaStream;
ObjectMapper mapper = (ObjectMapper) jp.getCodec();
ObjectNode root = (ObjectNode) mapper.readTree(jp);
JsonNode type = root.get("type");
System.out.println("type is "+type);
if (type.textValue().equals("latlng")) {
variantStravaStream = StravaStream2D.class;
} else {
variantStravaStream = StravaStream1D.class;
}
System.out.println("variant is "+variantStravaStream.getSimpleName());
return mapper.readValue(jp, variantStravaStream);
}
}
}
When I only ask for one dimensional data, like distance objects or so, it works out fine. But when I try to parse the "latlng" float[][], jackson fails. I am sure that the type is recognized, see the additonal system.out, it prints that a StravaStream2D.class variant is used.
The error message (and the additional system out) I get is:
01-26 09:05:49.605 27165-27165/nl.jfvh.stravatest I/System.out: type is "latlng"
01-26 09:05:49.605 27165-27165/nl.jfvh.stravatest I/System.out: variant is StravaStream2D
01-26 09:05:49.620 27165-27165/nl.jfvh.stravatest W/System.err: com.fasterxml.jackson.databind.JsonMappingException: Can not deserialize instance of float[] out of VALUE_NUMBER_FLOAT token
01-26 09:05:49.620 27165-27165/nl.jfvh.stravatest W/System.err: at [Source: java.io.StringReader#e8550ec; line: 1, column: 40164] (through reference chain: java.util.ArrayList[0]->nl.jfvh.stravatest.client.model.StravaStream2D["data"]->[Ljava.lang.Object[][0])
Is my data model wrong? The parsing of polymorphic objects is very new for me, I followed some tutorials, but the problems seems to be in the simple mapping of the data on the float[][]...

Since (according to you) you are new to parsing polymorphic objects, I'd suggest using annotations instead of a custom deserialiser. It's as simple as:
#JsonTypeInfo(use = JsonTypeInfo.Id.NAME, property = "type", visible = true)
#JsonSubTypes({
#JsonSubTypes.Type(name = "latlng", value = StravaStream.StravaStream2D.class),
#JsonSubTypes.Type(name = "distance", value = StravaStream.StravaStream1D.class)
})
public class StravaStream {
Read docs for JsonTypeInfo and JsonSubTypes
An issue with the custom deserialiser you're trying with is that when you do return mapper.readValue(jp, variantStravaStream); at the end it will actually re-enter the deserializer because class StravaStream2D extends StravaStream so Jackson will use the custom deserializer again. I got stack overflow errors when trying this due to infinite recursion.

Related

How to deserialize a json array followed by a normal property into a pojo in jackson. The array alone works

The difficulty is, that the json labels are partly dynamic in the rest response of the Kraken api. At first I introduce a working case. I connect the Kraken trading api to fetch currencies as assets and got the following result in json.
{
"error": [],
"result": {
"AAVE": {
"aclass": "currency",
"altname": "AAVE",
"decimals": 10,
"display_decimals": 5
},
"ZUSD": {
"aclass": "currency",
"altname": "USD",
"decimals": 4,
"display_decimals": 2
}
}
}
AAVA and ZUSD in this example are dynamic labels. I use the embedded Jackson to parse it in the OpenFeign framework. The result part are covered with the following generic class:
public class Response<T> {
private List<String> error = new ArrayList<>();
private T result;
// getter and setters
}
And as root class for the assets, the dynamic labels AAVA and ZUSD are handled by a Map:
public class AssetInfoResponse extends
Response<Map<String, AssetInfo>> {
}
The pojo AssetInfo:
public class AssetInfo implements Serializable{
#JsonProperty("altname")
private String alternateName;
#JsonProperty("aclass")
private String assetClass;
#JsonProperty("decimals")
private Byte decimals;
#JsonProperty("display_decimals")
private Byte displayDecimals;
// getters, setters ...
}
The above case works perfectly, also the solution with the dynamic labels.
Here is the response with the ohlc data, that looks similar and I have no Idea to solve the deserialization problem in the next case:
{
"error": [],
"result": {
"XXBTZEUR": [
[
1613212500,
"39000.1",
"39010.1",
"38972.3",
"38994.1",
"38998.1",
"3.23811638",
70
],
[
1613212560,
"38994.3",
"39014.5",
"38994.3",
"39014.5",
"38997.3",
"0.95105956",
11
]
],
"last": 1613212500
}
}
The cause of the problem is the "last": 1613212500 property line. When I remove this line, the response can be parsed without problems. I try to solve it with the following classes, Response is the upper described class.
public class OhlcLastResponse<T> extends Response<T> {
private Long last;
// getters and setters
}
The next class extends the prevourious class and is the root class for the objectmapper:
public class OhlcResponse
extends OhlcLastResponse<Map<String, List<Candelstick>>> {
}
And the pojo that holds the candlestick data:
#JsonFormat(shape = JsonFormat.Shape.ARRAY)
#JsonPropertyOrder({ "time", "open", "high", "low",
"close", "vwap", "volume", "count" })
public class Candelstick implements Serializable {
private Integer time;
private BigDecimal open;
private BigDecimal high;
private BigDecimal low;
private BigDecimal close;
private BigDecimal vwap;
private BigDecimal volume;
private Integer count;
// getters and setters ...
}
and here is the error:
"38997.3",
"0.95105956",
11
]
],
"last": 1613212500
}
}
"; line: 26, column: 11] (through reference chain: OhlcResponse["result"]->java.util.LinkedHashMap["last"])
at com.fasterxml.jackson.databind.exc.MismatchedInputException.from(MismatchedInputException.java:59)
Jackson tries to put the last property into the map, but the map was finished by ],. Line 26 is the line with the
last label in the json file.
Is there a possibility to parse this json? I think it must be possible, because the array is closed by the square bracket.
I hosted the rest client on github. To reproduce the error just clone it and run mvn test.
The solution is a deserializer, because the type handling is very difficult in this case. The deserializer decide between the two cases, array or the single last value, and call in the case of an array the deserializer for the CandleStick Class:
public class OhlcDeserializer extends JsonDeserializer<OhclPayload> {
#Override
public OhclPayload deserialize(JsonParser p, DeserializationContext ctxt)
throws IOException, JsonProcessingException {
List<CandleStick> candleSticks = new ArrayList<CandleStick>();
Long last = null;
ObjectCodec objectCodec = p.getCodec();
JsonNode jsonNode = objectCodec.readTree(p);
Iterator<Entry<String, JsonNode>> payloadIterator = jsonNode.fields();
while (payloadIterator.hasNext()) {
Map.Entry<String, JsonNode> entry = payloadIterator.next();
if (entry.getKey().equals("last")) {
last = entry.getValue().asLong();
} else if (entry.getValue().isArray()) {
for (JsonNode node : entry.getValue()) {
CandleStick cs = p.getCodec().treeToValue(node, CandleStick.class);
candleSticks.add(cs);
}
}
}
return new OhclPayload(candleSticks, last);
}
}
I changed the OhclResponse to:
public class OhlcResponse extends Response<OhclPayload> {
}
And insert a OhlcPayload class for the deserializer:
#JsonDeserialize(using = OhlcDeserializer.class)
public class OhclPayload {
private List<CandleStick> candleSticks;
private Long last;
// getters and setters
}
Thats all.

How to deserialize a generic type with jackson?

I tried many solutions, but my case seems special. The #JsonProperty must be depending on class type:
I have JSON for two entities:
"Person": [ { "id": "452009517701", "name": "Perosn1",
"address": "541-DPL-355" } ]
"Car": [ { "id": 5787544, "brand": "Toyota", "number":
12454 } ]
The entities look like :
public class Person{
private String id:
private String name;
private String address:
// Constcutors && Getters && Setters
}
public class Car{
private Long id:
private String brand;
private Long number:
// Constcutors && Getters && Setters
}
The generic class :
public class GenericEntity<T>{
//#JsonProperty
private List<T> myList;
// Constcutors && Getters && Setters
}
Main class :
public static void main(String[] args) {
ObjectMapper mapper=new ObjectMapper();
GenericEntity p=mapper.readValue(personJson,GenericEntity.class);
GenericEntity c=mapper.readValue(carJson,GenericEntity.class);
}
When I debug I find that the lists inside GenericEntity are always null. I do not know how to set jsonProperty dynamically on the top of the list inside the GenericEntity.
Also, i used :
Object readValue = mapper.readValue(jsonPerson, new TypeReference<GenericEntity<Person>>() {});
And :
JavaType javaType = mapper.getTypeFactory().constructParametricType(GenericEntity.class, Person.class);
Object readValue =mapper.readValue(jsonPerson, javaType);
Bu i got this :
Exception in thread "main" com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot construct instance of `com.test.GenericEntity` (although at least one Creator exists): no String-argument constructor/factory method to deserialize from String value ('Person')
at [Source: (String)""Person": [ { "id": "452009517701", "name": "Perosn1", "address": "541-DPL-355" } ]"; line: 1, column: 1]
at com.fasterxml.jackson.databind.exc.MismatchedInputException.from(MismatchedInputException.java:63)
at com.fasterxml.jackson.databind.DeserializationContext.reportInputMismatch(DeserializationContext.java:1343)
at com.fasterxml.jackson.databind.DeserializationContext.handleMissingInstantiator(DeserializationContext.java:1032)
at com.fasterxml.jackson.databind.deser.ValueInstantiator._createFromStringFallbacks(ValueInstantiator.java:371)
at com.fasterxml.jackson.databind.deser.std.StdValueInstantiator.createFromString(StdValueInstantiator.java:323)
at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.deserializeFromString(BeanDeserializerBase.java:1373)
at com.fasterxml.jackson.databind.deser.BeanDeserializer._deserializeOther(BeanDeserializer.java:171)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:161)
at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:4013)
The simplest option would be to use a wrapper type with a separate field per collection type, like that:
class GenericEntity {
#JsonProperty("Car") List<Car> car;
#JsonProperty("Person") List<Person> person;
}
This way you would always have one of those lists filled (according to our conversation in comments). This will work fine as long as you don't have too many types and it doesn't change too frequently :)
The more-advanced way would be to use a custom deserializer, like that:
#JsonDeserialize(using = MyDeserializer.class)
class GenericEntity<T> {
List<T> myList;
GenericEntity(List<T> myList) {
this.myList = myList;
}
}
The deserializer itself would have to create a GenericEntity on its own, but it can delegate all specific-type-deserializing job to other deserializers (so our job would be just to tell it what to deserialize and to what type):
class MyDeserializer extends JsonDeserializer<GenericEntity<?>> {
#Override
public GenericEntity<?> deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
ObjectCodec codec = p.getCodec();
JsonNode node = codec.readTree(p);
if (node.hasNonNull("Person")) {
JsonParser nodeParser = node.get("Person").traverse(codec);
nodeParser.nextToken();
Person[] people = ctxt.readValue(nodeParser, Person[].class);
return new GenericEntity<>(asList(people));
} else if (node.hasNonNull("Car")) {
JsonParser nodeParser = node.get("Car").traverse(codec);
nodeParser.nextToken();
Car[] cars = ctxt.readValue(nodeParser, Car[].class);
return new GenericEntity<>(asList(cars));
}
throw new RuntimeException("Couldn't find a type to deserialize!");
}
}

Deserialization of JSON array

I'm not sure how to deserialize array containing plain strings.I'm trying to parse the following JSON
{
"state":"RT",
"testMethod":"electronic",
"testElements":[
{
"testId":[
"UT_ITXref",
"Fed_ITXref"
]
},
"testStartDate",
"testEndDate",
"testDueDate"
]
}
I'm getting the following error:
com.fasterxml.jackson.databind.JsonMappingException: Can not construct instance of com.test.rules.model.TestElements: no String-argument constructor/factory method to deserialize from String value ('testStartDate')
at [Source: {"state":"RT","testMethod":"electronic","testElements":[{"testId":["UT_ITXref","Fed_ITXref"]},"testStartDate","testEndDate","testDueDate"}]}; line: 1, column: 247] (through reference chain: com.test.rules.model.TestRules["testElements"]->java.lang.Object[][1])
at com.fasterxml.jackson.databind.JsonMappingException.from(JsonMappingException.java:270)
at com.fasterxml.jackson.databind.DeserializationContext.instantiationException(DeserializationContext.java:1456)
at com.fasterxml.jackson.databind.DeserializationContext.handleMissingInstantiator(DeserializationContext.java:1012)
at com.fasterxml.jackson.databind.deser.ValueInstantiator._createFromStringFallbacks(ValueInstantiator.java:370)
at com.fasterxml.jackson.databind.deser.std.StdValueInstantiator.createFromString(StdValueInstantiator.java:315)
at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.deserializeFromString(BeanDeserializerBase.java:1282)
at com.fasterxml.jackson.databind.deser.BeanDeserializer._deserializeOther(BeanDeserializer.java:159)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:150)
at com.fasterxml.jackson.databind.deser.std.ObjectArrayDeserializer.deserialize(ObjectArrayDeserializer.java:196)
at com.fasterxml.jackson.databind.deser.std.ObjectArrayDeserializer.deserialize(ObjectArrayDeserializer.java:20)
at com.fasterxml.jackson.databind.deser.SettableBeanProperty.deserialize(SettableBeanProperty.java:499)
at com.fasterxml.jackson.databind.deser.BeanDeserializer._deserializeWithErrorWrapping(BeanDeserializer.java:511)
at com.fasterxml.jackson.databind.deser.BeanDeserializer._deserializeUsingPropertyBased(BeanDeserializer.java:396)
at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.deserializeFromObjectUsingNonDefault(BeanDeserializerBase.java:1198)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserializeFromObject(BeanDeserializer.java:314)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:148)
at com.fasterxml.jackson.databind.ObjectReader._bindAndClose(ObjectReader.java:1626)
at com.fasterxml.jackson.databind.ObjectReader.readValue(ObjectReader.java:1220)
Here is what I did , I used #JsonCreator annotation to deserialize
public class TestRules {
private String state;
private String testMethod;
private TestElements[] testElements;
#JsonCreator
public TaxRules(
#JsonProperty("state") String state,
#JsonProperty("testMethod") String testMethod,
#JsonProperty("testElements") TestElements[] testElements
) {
this.state = state;
this.testMethod = testMethod;
this.testElements = testElements;
}
}
public class TestElements {
private List<String> testId;
private List<String> elements;
public List<String> getElements() {
return elements;
}
public void setElements(List<String> elements) {
this.elements = elements;
}
public List<String> getTestId() {
return testId;
}
public void setTestId(List<String> testId) {
this.testId = testId;
}
}
Should I write custom deserializer or Is there any way that I can use the jackson API for this. Any suggestions would be appreciated.
Actually errors tells something.
JSON parser found that for testElements property there is an Array of Objects, but your Json file has mixed content.
first element is an object (I assume it is TestElement class). Then parser creates that object with empty constructor and calls appropriate setters for its properties.
but...
second,third and forth elements are String, so error says that parser tries to find constrictor with String as argument.
So, you may try to make that constructor in TestElement class and see will it work or not...
Do not forget to keep empty constructor as well.
I cannot guarantee it will work but, at least error says that.
BTW are you sure your Json object is correct? but not something like that?
{
"state":"RT",
"testMethod":"electronic",
"testElements":[
{
"testId":[
"UT_ITXref",
"Fed_ITXref"
]
}],
"testStartDate":"01-01-2017",
"testEndDate":"01-02-2017",
"testDueDate":"01-03-2017"
}
I'm a little confused because StartDate, EndDate, DueDate semantically look more like test attributes, not as elements in testElements array
{
"state": "RT",
"testMethod": "electronic",
"testElements": [
{
"testId": [
"UT_ITXref", // <-- this object is deserialized just fine
"Fed_ITXref"
]
},
"testStartDate", // <-- this is where the error is happening
"testEndDate",
"testDueDate"
]
}
Did you intend the json to be interpreted as if it looked like the following?
{
"state": "RT",
"testMethod": "electronic",
"testElements": [
{
"testId": [
"UT_ITXref",
"Fed_ITXref"
]
},
{
testId: [
"testStartDate"
]
},
{
testId: [
"testEndDate"
]
},
{
testId: [
"testDueDate"
]
}
]
}
If so, you'll need to make a custom deserializer to detect whether the element in the array is an object or a string. If it's a string, you'll probably want to construct the TestElement yourself.

JSON Deep Mapping

Is it possible to map a field which is deeper in a json-response to a property in an object - in other words: transform a json which hierarchy into a flat object?
For example I would like to annotate the 'user_id' property of the Marker class with 'links.user.id'.
I have looked into GSON and Jackson, but couldn't find a solution.
Json-Response for a Marker:
{
"id": 791,
"name": "Marker42",
"links": {
"user": {
"href": "http://4242.com/users/970",
"id": 970
}
}
Data-Model:
public class Marker {
#SerializedName("id")
private int id;
#SerializedName("name")
private String name;
#SerializedName("links.user.id")
private int user_id;
}
This isn't pretty but you can set your own deserialiser in GSON. I am not as familiar with Jackson but this tutorial shows a very similar method: http://www.baeldung.com/jackson-deserialization
public static class MarkerGSONDeserializer implements JsonDeserializer<Marker>{
#Override
public Marker deserialize(JsonElement data, Type arg1, JsonDeserializationContext arg2) throws JsonParseException {
if(!data.isJsonObject()){
return null;
} else {
JsonObject obj = data.getAsJsonObject();
Marker res = new Marker();
res.setId(obj.get("id").getAsInt());
res.setName(obj.get("name").getAsString());
res.setUserId(((obj.get("links").getAsJsonObject())).get("user").getAsJsonObject()).get("id").getAsInt();
return res;
}
}
}

Deserialize Generic class Jackson or Gson

From the land of .NET I have a generic class define like so..
public class SyncWrapper<T, I>
{
public IList<T> Data { get; set; }
public IList<I> DeleteIds { get; set; }
public DateTime LastSyncDateTime { get; set; }
}
I was able to create an instance of this object from json by simply calling ...
JsonConvert.DeserializeObject<SyncWrapper<T, Guid>>(json);
Now I've been given the task of porting this code over to Java/Android. Having never touched Java before, I've a lot to learn!
Anyway, so far I've tried Gson and Jackson to get the object from json but no joy. I think that I won't be able to call andthing with the <T> involved gson.fromJson(json, SyncWrapper<T, UUID>.class) for example as there is a problem with type Erasure!
My efforts so far have looked like this....
Gson
Gson gson = new Gson();
SyncWrapper<MyClass, UUID> result = gson.fromJson(json, new TypeToken<SyncWrapper<MyClass, UUID>>() { }.getType());
This compiles but the result is an empty SyncWrapper
Jackson
ObjectMapper mapper = new ObjectMapper();
SyncWrapper<MyClass, UUID> result = mapper.readValue(json, new TypeReference<SyncWrapper<MyClass, UUID>>() { });
This compiles but crashes the app when executed!!!
My Java version of SyncWrapper....
public class SyncWrapper<T, I> {
private DateTime lastSyncDateTime;
private Collection<T> data;
private Collection<I> deleteIds;
public Collection<T> getData() {
return data;
}
public void setData(Collection<T> data) {
this.data = data;
}
public Collection<I> getDeleteIds() {
return deleteIds;
}
public void setDeleteIds(Collection<I> deleteIds) {
this.deleteIds = deleteIds;
}
public DateTime getLastSyncDateTime() {
return lastSyncDateTime;
}
public void setLastSyncDateTime(DateTime lastSyncDateTime) {
this.lastSyncDateTime = lastSyncDateTime;
}
}
I've been really thrown in at the deep end by the powers that be (all programming is the same isn't it?), so any help really appreciated.
I'm not precious about which library I use (Gson, Jackson, etc)
Update
An example of the Json that is to be deserialized...
{
"Data": [
{
"Name": "Company A",
"Id": "7d5d236c-c2b5-42dc-aea5-99e6752c8a52"
},
{
"Name": "Company B",
"Id": "44444444-0000-0000-0000-444444444444"
},
{
"Name": "Company C",
"Id": "249a4558-05c6-483f-9835-0056804791c9"
}
],
"DeleteIds": [
"5f7873a6-b2ee-4566-9714-1577b81384f4",
"1f224a39-16c3-441d-99de-8e58fa8f31c2"
],
"LastSyncDateTime": "\/Date(1393580073773+0000)\/"
}
..or this (more often than not, the DeleteIds will be null)...
{
"Data": [
{
"Name": "Company A",
"Id": "7d5d236c-c2b5-42dc-aea5-99e6752c8a52"
},
{
"Name": "Company B",
"Id": "44444444-0000-0000-0000-444444444444"
},
{
"Name": "Company C",
"Id": "249a4558-05c6-483f-9835-0056804791c9"
}
],
"DeleteIds": null,
"LastSyncDateTime": "\/Date(1393580073773+0000)\/"
}
For the above json I would be mapping to a SyncWrapper where T is Company...
public class Company extends ModelBase {
private String name;
public Company(UUID id, String name) {
super(id);
setName(name);
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
Here's the issues:
Your field names in your Java classes don't match the field names in the JSON; capitalization matters. This is why you're getting back absolutely nothing after parsing.
I'm going to go with Gson examples simply because I know that off the top of my head. You can do the same things in Jackson, but I'd need to look them up:
public class SyncWrapper<T, I> {
#SearializedName("LastSyncDateTime")
private DateTime lastSyncDateTime;
#SearializedName("Data")
private Collection<T> data;
#SearializedName("DeleteIds")
private Collection<I> deleteIds;
This tells Gson which fields in Java map to the fields in JSON. You could also go with a field naming policy instead, since it looks like all your fields are upper camel case:
Gson g = new GsonBuilder()
.setFieldNamingPolicy(FieldNamingPolicy.UPPER_CAMEL_CASE)
.build();
Now your fields will match up. The next issue is going to be that UUID class. That class in Java is not a string; it's a class that generates UUIDs. Just use String for the type that holds it in your Java class.
The DateTime class ... same issue. And on top of that you've got a bit of a weird value in your JSON for the date. You'll either want to store that as a String as well, or you're going to have to write a custom deserializer to deal with it.
With those changes, I think you're good to go.
Edit to add from the comments: If you really need the Java UUID class rather than just the String representation, you can write a chunk of code that takes care of this for you:
class UUIDDeserializer implements JsonDeserializer<UUID>
{
#Override
public UUID deserialize(JsonElement je, Type type, JsonDeserializationContext jdc) throws JsonParseException
{
return UUID.fromString(je.getAsString());
}
}
You can then register this with Gson:
Gson g = new GsonBuilder()
.setFieldNamingPolicy(FieldNamingPolicy.UPPER_CAMEL_CASE)
.registerTypeAdapter(UUID.class, new UUIDDeserializer())
.build();
This will populate the UUID typed fields in your class with UUID instances. This is the same thing you'd need to do with that funky date value.
I suggest using Jackson for this; it has a more clear API and does not require creating a new type as Gson (where you have to extend a class to be able to do that).
Example:
public static <T> T fromJsonToGenericPojo(
String json, Class<?> classType, Class<?>... genericTypes) {
JavaType javaType = TypeFactory.defaultInstance()
.constructParametricType(classType, genericTypes);
try {
return OBJECT_MAPPER.readValue(json, javaType);
} catch (IOException e) {
LOGGER.error(e.getMessage(), e);
throw new IllegalArgumentException(e);
}
}

Categories

Resources