在没有适当字段的情况下用杰克逊反序列化JSON

时间:2012-07-03 16:40:27

标签: java json jackson

我有这个JSON:{“成功”:false}

我想将此反序列化为此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));
    }
}

是否可以将此JSON反序列化为没有字段成功的类? 到目前为止,我总是得到“UnrecognizedPropertyException:Unrecognized field”成功“”

感谢您的帮助!

3 个答案:

答案 0 :(得分:6)

您可以实现一个方法并使用@JsonAnySetter注释它,如下所示:

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

另一种可能性就是这样失败:

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

这可以让你在没有找到属性的情况下反序列化你的JSON。

测试


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));
}

答案 1 :(得分:0)

注意:我是EclipseLink JAXB (MOXy)主管,是JAXB (JSR-222)专家组的成员。

如果您无法与Jackson合作,以下是您如何使用MOXy支持此用例。

<强>消息

Message课程不需要注释。默认情况下,使用属性访问。您可以使用@XmlAccessorType(XmlAccessType.FIELD)指定字段访问权限,请参阅: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

要将MOXy指定为JAXB提供程序,您需要在与域模型相同的包中包含名为jaxb.properties的文件,并带有以下条目:

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

<强>演示

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);
    }

}

<强>输入/输出

{"success":false}

答案 2 :(得分:0)

我不明白这个问题。杰克逊将(de)从原始问题中定义的消息POJO的当前版本序列化,没有错误,没有任何特殊配置(除了@JsonProperty注释)。当前的消息POJO没有名为success的字段,但它确定了一个名为success的属性,这就是为什么Jackson很乐意将示例JSON映射到它而没有任何成功其他配置。您要删除@JsonProperty注释吗?

如果是这种情况,那么你可以这样做,并且Jackson仍然会(或)使用相同的示例JSON从消息POJO序列化,而不需要任何其他配置,因为isSuccess和setSuccess方法签名已经充分定义了Message有一个名为success的属性,它匹配JSON中的元素名称。

以下示例说明了这些要点。

示例1,消息POJO完全按照原始问题中的定义:

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));
  }
}

示例2,修改了消息POJO以删除@JsonProperty注释。

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));
  }
}

使用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;
}