Deserialize JSON with Jackson without proper field

I have this JSON: {"success": false}

I want to deserialize this in this POJO:

class Message { private Map<String, String> dataset = new HashMap<String, String>(); @JsonProperty("success") public boolean isSuccess() { return Boolean.valueOf(dataset.get("success")); } @JsonProperty("success") public void setSuccess(boolean success) { dataset.put("success", String.valueOf(success)); } } 

Is it possible to deserialize this JSON into a class without success in the field? So far, I always have "UnrecognizedPropertyException: Unrecognized field" success ""

Thanks for your help!

+6
source share
3 answers

You can implement the method and annotate it using @JsonAnySetter as follows:

 @JsonAnySetter public void handleUnknownProperties(String key, Object value) { // this will be invoked when property isn't known } 

Another possibility is to disable it like this:

 objectMapper.configure(DeserializationConfig.Feature.FAIL_ON_UNKNOWN_PROPERTIES, false); 

This will allow you to deserialize your JSON without crashing when properties are not found.

Test


 public static class Message { private final Map<String, String> dataset = new HashMap<String, String>(); @Override public String toString() { return "Message [dataset=" + dataset + "]"; } } @Test public void testJackson() throws JsonParseException, JsonMappingException, IOException { String json = "{\"success\":false}"; ObjectMapper om = new ObjectMapper().configure(DeserializationConfig.Feature.FAIL_ON_UNKNOWN_PROPERTIES, false); System.out.println(om.readValue(json, Message.class)); } 
+5
source

Note. I am an EclipseLink JAXB (MOXy) and a member of the JAXB Group (JSR-222) .

If you cannot get it to work with Jackson, the following shows how you can support this use case with MOXy.

Message

In the Message class, annotations are not required. By default, access to properties is used. You can specify access to the field using @XmlAccessorType(XmlAccessType.FIELD) , see http://blog.bdoughan.com/2011/06/using-jaxbs-xmlaccessortype-to.html .

 package forum11315389; import java.util.*; class Message { private Map<String, String> dataset = new HashMap<String, String>(); public boolean isSuccess() { return Boolean.valueOf(dataset.get("success")); } public void setSuccess(boolean success) { dataset.put("success", String.valueOf(success)); } } 

jaxb.properties

To specify MOXy as your JAXB provider, you need to include a file named jaxb.properties in the same package as your domain model, with the following entry:

 javax.xml.bind.context.factory=org.eclipse.persistence.jaxb.JAXBContextFactory 

Demo

 package forum11315389; import java.io.StringReader; import java.util.*; import javax.xml.bind.*; import javax.xml.transform.stream.StreamSource; import org.eclipse.persistence.jaxb.JAXBContextProperties; public class Demo { public static void main(String[] args) throws Exception { Map<String,Object> properties = new HashMap<String,Object>(1); properties.put(JAXBContextProperties.MEDIA_TYPE, "application/json"); properties.put(JAXBContextProperties.JSON_INCLUDE_ROOT, false); JAXBContext jc = JAXBContext.newInstance(new Class[] {Message.class}, properties); StreamSource json = new StreamSource(new StringReader("{\"success\":false}")); Unmarshaller unmarshaller = jc.createUnmarshaller(); Message message = unmarshaller.unmarshal(json, Message.class).getValue(); Marshaller marshaller = jc.createMarshaller(); marshaller.marshal(message, System.out); } } 

Input Output

 {"success":false} 
0
source

I do not understand the question. Jackson will (de) serialize from / to the current version of Message POJO, which you defined in the original question, just fine, without errors, and without any special configurations (except @JsonProperty annotations). There is no successful field name in the current Message POJO, but it defines a property named success, so Jackson is happy to match the JSON example with it without any additional configurations. Do you want to remove @JsonProperty annotations?

If so, then you can do it, and Jackson still (de) serializes from / to Message POJO with the same JSON example without any other configurations, because the isSuccess and setSuccess method signatures already adequately determine that the Message has a property named success that matches the name of the element in JSON.

The following examples demonstrate these points.

Example 1 with a POJO message exactly as defined in the original question:

 import java.util.HashMap; import java.util.Map; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.databind.ObjectMapper; public class JacksonFoo { public static void main(String[] args) throws Exception { // input: {"success":false} String inputJson = "{\"success\":false}"; ObjectMapper mapper = new ObjectMapper(); Message message = mapper.readValue(inputJson, Message.class); System.out.println(mapper.writeValueAsString(message)); // output: {"success":false} } } class Message { private Map<String, String> dataset = new HashMap<String, String>(); @JsonProperty("success") public boolean isSuccess() { return Boolean.valueOf(dataset.get("success")); } @JsonProperty("success") public void setSuccess(boolean success) { dataset.put("success", String.valueOf(success)); } } 

Example 2 with a POJO message modified to remove @JsonProperty annotations.

 import java.util.HashMap; import java.util.Map; import com.fasterxml.jackson.databind.ObjectMapper; public class JacksonFoo { public static void main(String[] args) throws Exception { // input: {"success":false} String inputJson = "{\"success\":false}"; ObjectMapper mapper = new ObjectMapper(); Message message = mapper.readValue(inputJson, Message.class); System.out.println(mapper.writeValueAsString(message)); // output: {"success":false} } } class Message { private Map<String, String> dataset = new HashMap<String, String>(); public boolean isSuccess() { return Boolean.valueOf(dataset.get("success")); } public void setSuccess(boolean success) { dataset.put("success", String.valueOf(success)); } } 

Example with MessageWrapper:

 public class JacksonFoo { public static void main(String[] args) throws Exception { // input: {"success":false} String inputJson = "{\"success\":true}"; ObjectMapper mapper = new ObjectMapper(); MessageWrapper wrappedMessage = mapper.readValue(inputJson, MessageWrapper.class); System.out.println(mapper.writeValueAsString(wrappedMessage)); // output: {"success":true} } } class MessageWrapper { @JsonUnwrapped @JsonProperty // exposes non-public field for Jackson use Message message; } 
0
source

Source: https://habr.com/ru/post/919606/


All Articles