6

我有这个 JSON:{"success":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:无法识别的字段“成功””

谢谢你的帮助!

4

3 回答 3

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));
}
于 2012-07-03T16:48:45.797 回答
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}
于 2012-07-03T20:39:51.837 回答
0

我不明白这个问题。Jackson 将从/到您在原始问题中定义的 Message POJO 的当前版本(反)序列化,没有错误,也没有任何特殊配置(@JsonProperty 注释除外)。当前的 Message POJO 没有名为 success 的字段,但它确实定义了一个名为 success 的属性,这就是 Jackson 乐于将示例 JSON 映射到它而无需任何额外配置的原因。是否要删除 @JsonProperty 注释?

如果是这种情况,那么您可以这样做,并且 Jackson 仍将使用相同的示例 JSON 从/向 Message POJO(反)序列化,而无需任何其他配置,因为 isSuccess 和 setSuccess 方法签名已经充分定义 Message 具有名为 success 的属性,与 JSON 中的元素名称匹配。

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

带有消息 POJO 的示例 1 与原始问题中的定义完全一致:

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 修改了 Message 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;
}
于 2012-07-04T01:06:36.780 回答