杰克逊-允许前导零并保留它们

时间:2018-12-17 17:11:56

标签: java json jackson

我有以下Java Bean:

public class Something {

    @NotBlank
    private final String value;

    @JsonCreator
    public Something(@JsonProperty("value")final String value) {
        this.value = value;
    }

    public String getValue() {
        return value;
    }

    @Override
    public boolean equals(final Object o) {
        return EqualsBuilder.reflectionEquals(this, o);
    }

    @Override
    public int hashCode() {
        return HashCodeBuilder.reflectionHashCode(this);
    }
}

以及以下用于处理json序列化和反序列化的实用程序类

public class JsonUtils {

    private final ObjectMapper objectMapper;

    @Inject
    public JsonUtils(final ObjectMapper objectMapper) {
        this.objectMapper = objectMapper;
    }

    public <T> T jsonToObject(final String jsonString, final Class<T> classType) {

        try {
            return objectMapper.readValue(jsonString, classType);
        } catch (IOException e) {
            throw new JsonException(ErrorMessage.ERROR_PARSE_JSON_TO_OBJECT, e);
        }
    }

    public <V> String objectToJson(final V objectToBeParsed) {

        try {
            return objectMapper.writeValueAsString(objectToBeParsed);
        } catch (IOException e) {
            throw new JsonException(ErrorMessage.ERROR_PARSE_OBJECT_TO_JSON, e);
        }
    }
}

我的对象映射器在这里配置

public class ParserModule extends AbstractModule {

    @Provides
    public ObjectMapper getObjectMapper() {

        final ObjectMapper objectMapper = new ObjectMapper();
        objectMapper.disable(WRITE_DATES_AS_TIMESTAMPS);
        objectMapper.enable(ALLOW_NUMERIC_LEADING_ZEROS);

        objectMapper.findAndRegisterModules();
        objectMapper.registerModule(getSerializersModule());
        objectMapper.registerModule(getDeserializerModule());

        return objectMapper;
    }

    private SimpleModule getSerializersModule() {

        final SimpleModule simpleModule = new SimpleModule();
        simpleModule.addSerializer(Something.class, new SomethingSerializer());

        return simpleModule;
    }

    private SimpleModule getDeserializerModule() {

        final SimpleModule simpleModule = new SimpleModule();
        simpleModule.addDeserializer(Something.class, new SomethingDeserializer());

        return simpleModule;
    }
}

最后,此JSON对象将是REST API响应主体中的返回值,但API规范要求仅包含“值”字段值的原始字符串。因此,如果我的事物的值为"hello world",它应该在响应正文中返回hello world,而不是{"value":"hello world"}

该规范不是我定义的,我必须遵守,并且它不可能改变。

因此,我创建了以下序列化器和反序列化器,它们已在对象映射器中注册,如前所述

public class SomethingSerializer extends StdSerializer<Something> {

    public SomethingSerializer() {
        this(null);
    }

    public SomethingSerializer(final Class<Something> t) {
        super(t);
    }

    @Override
    public void serialize(final Something something, final JsonGenerator jsonGenerator, final SerializerProvider serializerProvider) throws IOException {
        jsonGenerator.writeRawValue(something.getValue());
    }
}

public class SomethingDeserializer extends StdDeserializer<Something> {

    public SomethingDeserializer() {
        this(null);
    }

    public SomethingDeserializer(final Class<?> t) {
        super(t);
    }

    @Override
    public Something deserialize(final JsonParser jsonParser, final DeserializationContext context) throws IOException {
        return new Something(jsonParser.getCodec().readTree(jsonParser).toString());
    }
}

现在我在某物对象中拥有的实际值不是"hello world",而是一个看起来像这样的字符串:01.something.this.that.org。注意这里的前导零。

因此,每当我尝试反序列化这样的对象时:

Something result = jsonUtils.jsonToObject(response.getBody(), Something.class);

我得到一个例外:

JsonParseException: Invalid numeric value: Leading zeroes not allowed
 at [Source: (String)"01.something.this.that.org"; line: 1, column: 2]

在Jackson的源代码中研究了这个异常之后,我发现有一个功能可以让我“跳过”这个异常,并且我以为我找到了解决方案,所以我将其添加到了对象映射器中:

objectMapper.enable(ALLOW_NUMERIC_LEADING_ZEROS);

现在我不再收到异常了,很酷。但是反序列化的字符串变为:1.something.this.that.org。所以我回到第一场。

有什么办法吗?
1)开头的零没有例外
2)实际上保持前导零

谢谢。

编辑:

实际上,在添加允许前导零的功能之后,我的第一个测试是仅解析返回01的{​​{1}}值,但是如果我尝试解析此处给出的示例字符串,我得到另一个例外:

1

所以我想我的问题确实是,我如何让杰克逊将原始字符串解释为实际的字符串,因为目前看来它似乎将其解释为数字。

0 个答案:

没有答案