Reputation: 139
I've got this JSON : {"success":false}
I want to deserialize this into 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 field success? So far, i've always got the "UnrecognizedPropertyException: Unrecognized field "success""
Thanks for your help!
Upvotes: 6
Views: 10339
Reputation: 67023
I don't understand the question. Jackson will (de)serialize from/to the current version of the Message POJO you've defined in the original question just fine, without errors, and without any special configurations (other than the @JsonProperty annotations). The current Message POJO does not have a field named success, but it does define a property named success, which is why Jackson is happy to map the example JSON to it without any additional configurations. Are you wanting to remove the @JsonProperty annotations?
If that's the case, then you can do so, and Jackson will still (de)serialize from/to the Message POJO with the same example JSON without any other configurations necessary, because the isSuccess and setSuccess method signatures already adequately define that Message has a property named success, which matches the element name in the JSON.
The following examples demonstrate these points.
Example 1 with Message POJO exactly as defined in 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 Message POJO 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;
}
Upvotes: 0
Reputation: 149057
Note: I'm the EclipseLink JAXB (MOXy) lead and a member of the JAXB (JSR-222) expert group.
If you can't get it to work with Jackson, below is how you can support this use case with MOXy.
Message
No annotations are required on the Message
class. By default property access is used. You can specify field access 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 called 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}
Upvotes: 0
Reputation: 23913
You could implement a method and annotate it with @JsonAnySetter
like this:
@JsonAnySetter
public void handleUnknownProperties(String key, Object value) {
// this will be invoked when property isn't known
}
another possibility would be turn this fail off like this:
objectMapper.configure(DeserializationConfig.Feature.FAIL_ON_UNKNOWN_PROPERTIES, false);
This would let you deserialize your JSON without failing when properties are not found.
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));
}
Upvotes: 6