I'm looking to deserialize any unknown fields in a JSON object as entries in a Map
which is a member of a POJO.
For example, here is the JSON:
{
"knownField" : 5,
"unknownField1" : "926f7c2f-1ae2-426b-9f36-4ba042334b68",
"unknownField2" : "ed51e59d-a551-4cdc-be69-7d337162b691"
}
Here is the POJO:
class MyObject {
int knownField;
Map<String, UUID> unknownFields;
// getters/setters whatever
}
Is there a way to configure this with Jackson? If not, is there an effective way to write a StdDeserializer
to do it (assume the values in unknownFields
can be a more complex but well known consistent type)?
@JsonProperty can change the visibility of logical property using its access element during serialization and deserialization of JSON. @JsonAlias defines one or more alternative names for a property to be accepted during deserialization.
We are using writeObject() method of ObjectOutputStream to serialize HashMap in Java. In the following program, we save the hashmap content in a serialized newHashMap file. Once you run the following code, a newHashMap file will be created. This file is used for deserialization in the next upcoming program.
Jackson API provides two ways to ignore unknown fields, first at the class level using @JsonIgnoreProperties annotation and second at the ObjectMapper level using configure() method.
The simple readValue API of the ObjectMapper is a good entry point. We can use it to parse or deserialize JSON content into a Java object. Also, on the writing side, we can use the writeValue API to serialize any Java object as JSON output.
ObjectMapper is Jackson's serialization mapper. It allows us to serialize our map, and write it out as a pretty-printed JSON String using the toString () method in String: 3.2. Map<Object, String> Serialization With a few extra steps, we can also serialize a map containing a custom Java class.
There is another option when we deserialize into a Java class that contains a Map; we can use Jackson's KeyDeserializer class, one of the many Deserialization classes that Jackson offers. Let's annotate our ClassWithAMap with @JsonCreator, @JsonProperty, and @JsonDeserialize:
Deserialization converts a stream of bytes into a Java object that we can use in code. In this section, we'll deserialize JSON input into Maps of different signatures. 4.1. Map<String, String> Deserialization
The issue I'm running into is that since the values in the serialized map do not have any type information, they are not deserialized correctly. For example, in the sample above, enumValue1 should be deserialized as an enum value but is instead deserialized as a String.
There is a feature and an annotation exactly fitting this purpose.
I tested and it works with UUIDs like in your example:
class MyUUIDClass {
public int knownField;
Map<String, UUID> unknownFields = new HashMap<>();
// Capture all other fields that Jackson do not match other members
@JsonAnyGetter
public Map<String, UUID> otherFields() {
return unknownFields;
}
@JsonAnySetter
public void setOtherField(String name, UUID value) {
unknownFields.put(name, value);
}
}
And it would work like this:
MyUUIDClass deserialized = objectMapper.readValue("{" +
"\"knownField\": 1," +
"\"foo\": \"9cfc64e0-9fed-492e-a7a1-ed2350debd95\"" +
"}", MyUUIDClass.class);
Also more common types like Strings work:
class MyClass {
public int knownField;
Map<String, String> unknownFields = new HashMap<>();
// Capture all other fields that Jackson do not match other members
@JsonAnyGetter
public Map<String, String> otherFields() {
return unknownFields;
}
@JsonAnySetter
public void setOtherField(String name, String value) {
unknownFields.put(name, value);
}
}
(I found this feature in this blog post first).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With