如果失败,如何配置objectMapper不创建新实例?

时间:2014-12-01 14:00:24

标签: java json serialization configuration jackson

我正在使用objectMapper,配置为:

protected ObjectMapper getCustomMapper() {
    if (this.mapper == null) {
        this.mapper = new ObjectMapper();
        this.mapper.configure(DeserializationConfig.Feature.FAIL_ON_UNKNOWN_PROPERTIES, false);
        this.mapper.setSerializationInclusion(Inclusion.NON_NULL);
    }
    return this.mapper;
}

我这样用它:

Email email = this.getCustomMapper().readValue(jsonResponse.toString(),           Email.class)

我的问题是如果映射失败,那么ObjectMapper会返回一个新的电子邮件实例,其所有属性都为null。我想知道是否存在某种方式告诉ObjectMapper如果他不能映射json然后返回null,而不是对象的新实例。你知道怎么做吗?此致

编辑:关于案例成功的Json输入是:

{  
   "user_id":"542d5f15e4b090c7c78c5938",
   "email":"test@gmail.com",
   "is_primary":true,
   "is_confirmed":true,
   "creation_date":"2014-10-02T14:20:05Z",
   "id":"542d5f15e4b090c7c78c5939"
}

我的Json输入案例失败是:

{  
   "code":40405,
   "message":"Email not found"
}

我希望如果请求失败,那么我的电子邮件对象为空。现在,电子邮件响应不是空的,而且他目前的所有属性都是。

2 个答案:

答案 0 :(得分:1)

Jackson不支持此功能,但您可以创建自定义反序列化程序,您可以在其中检查userName是否为null,并根据它返回null对象或转换后的对象。或者您可以选择其他字段或字段集。 在此解决方案中,每次在Email类中添加/更新/删除字段时都不需要更新反序列化器。

自定义反序列化器:

class EmailDeserializer extends JsonDeserializer<Email> {

    private JsonDeserializer<Email> delegate;

    EmailDeserializer(JsonDeserializer<Email> delegate) {
        this.delegate = delegate;
    }

    @Override
    public Email deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException {
        Email result = delegate.deserialize(jp, ctxt);

        if (result.getUserId() == null) {
            return null;
        }
        return result;
    }
}

如果您不想实现完全反序列化,则需要将委托反序列化器传递给构造函数。在这种情况下,每次更改/添加/删除Email类中的字段时,都不需要更新自定义反序列化程序。由于您正在传递构造函数参数,因此无法使用@JsonDeserialire注释,您需要直接注册它:

ObjectMapper objectMapper = new ObjectMapper();
objectMapper.configure(DeserializationConfig.Feature.FAIL_ON_UNKNOWN_PROPERTIES, false);
objectMapper.setSerializationInclusion(JsonSerialize.Inclusion.NON_NULL);

SimpleType simpleType = SimpleType.constructUnsafe(Email.class);
DeserializationConfig deserializationConfig = objectMapper.getDeserializationConfig();
JsonDeserializer deserializer = objectMapper.getDeserializerProvider().findTypedValueDeserializer(deserializationConfig, simpleType, null);

SimpleModule module = new SimpleModule("customModuleName", Version.unknownVersion());
module.addDeserializer(Email.class, new EmailDeserializer(deserializer));
objectMapper.registerModule(module);

答案 1 :(得分:1)

我宁愿将有效电子邮件和错误对象的反序列化分开。

有可能从代码中提到的jsonResponse变量中获取请求的状态。因此,如果状态代码是错误的(对于HTTP请求大于400),则输入JSON被视为错误,否则它被视为有效的电子邮件。

如果上述情况不可行,我会尝试根据某些属性的存在来猜测对象类型。这是一个例子:

public class JacksonDetectError {
    public static final String SUCCESS_JSON = "{  \n" +
            "   \"user_id\":\"542d5f15e4b090c7c78c5938\",\n" +
            "   \"email\":\"test@gmail.com\" \n" +
            "}";

    public static final String ERROR_JSON = "{  \n" +
            "   \"code\":40405,\n" +
            "   \"message\":\"Email not found\"\n" +
            "}";

    public static class Email {
        @JsonProperty("user_id")
        public String userId;
        public String email;

        @Override
        public String toString() {
            return "Email{" +
                    "userId='" + userId + '\'' +
                    ", email='" + email + '\'' +
                    '}';
        }
    }

    public static class Error {
        public int code;
        public String message;

        @Override
        public String toString() {
            return "Error{" +
                    "code=" + code +
                    ", message='" + message + '\'' +
                    '}';
        }
    }

    private static Object readJson(String jsonString) throws IOException {
        final ObjectMapper mapper = new ObjectMapper();
        final JsonNode json = mapper.readTree(jsonString);
        if (json.has("code")) {
            return mapper.readValue(json.traverse(), Error.class);
        }
        return mapper.convertValue(json, Email.class);
    }

    public static void main(String[] args) throws IOException {
        System.out.println(readJson(ERROR_JSON));
        System.out.println(readJson(SUCCESS_JSON));
    }
}

输出:

Error{code=40405, message='Email not found'}
Email{userId='542d5f15e4b090c7c78c5938', email='test@gmail.com'}