Обработка альтернативных имен свойств в десериализации Jackson

Я работаю над преобразованием службы REST/JSON из Coldfusion 9 в приложение Spring-MVC 3.1.. Я использую Jackson (1.9.5)и MappingJacksonJsonConverter, который предоставляет Spring, и настраиваю ObjectMapper для именования полей с помощью CAMEL_CASE_TO_LOWER_CASE_WITH _ПОДЧЕРКИВАЕТ.

Проблема, с которой я столкнулся, заключается в том, что наша устаревшая служба создает «верблюжий регистр в ЗАГЛАВНЫЙ регистр с символами подчеркивания» в качестве имен свойств json. Потребители этого JSON, также написанного на ColdFusion, могут меньше заботиться о регистре, но Джексон действительно заботится о регистре и выдает UnrecognizedPropertyExceptions.

Изучив почти все настройки, которые я мог получить из ObjectMapper -DeserializationConfig, DeserializerProvider и т. д., я пришел к очень запутанному хаку, в котором я анализирую дерево JSON, вывожу его с помощью специального JsonGenerator, который использует строчные буквы. имена полей, а затем анализирует их обратно как объект.

MappingJacksonHttpMessageConverter mc = new MappingJacksonHttpMessageConverter() {
    @Override
    protected Object readInternal(Class clazz, HttpInputMessage inputMessage) throws IOException, HttpMessageNotReadableException {
        return this.getObjectMapper().readValue(translateToLowerCaseKeys(inputMessage.getBody()), getJavaType(clazz));
    }

    private byte[] translateToLowerCaseKeys(InputStream messageBody) throws IOException {
        StringWriter sw = new StringWriter();
        JsonGenerator lowerCaseFieldNameGenerator = new JsonGeneratorDelegate(this.getObjectMapper().getJsonFactory().createJsonGenerator(sw)) {
            @Override
            public void writeFieldName(String name) throws IOException, org.codehaus.jackson.JsonGenerationException {
                delegate.writeFieldName(name.toLowerCase());
            };
        };
        this.getObjectMapper().writeTree(lowerCaseFieldNameGenerator, this.getObjectMapper().readTree(messageBody));
        lowerCaseFieldNameGenerator.close();
        return sw.getBuffer().toString().getBytes();
    }
};

Это решение кажется очень неэффективным. Существует решение , которое работает для ключей карты, но мне не удалось найти аналогичное решение для имен полей.

Альтернативное решение состоит в том, чтобы иметь два установщика, один из которых аннотирован устаревшим именем поля. Стратегия именования должна быть расширена, чтобы игнорировать эти поля, что в моей ситуации нормально, поскольку средство отображения объектов не будет иметь дело ни с какими другими классами со стратегией UPPER_UNDERSCORE :

public class JsonNamingTest {
    public static class CaseInsensitive extends LowerCaseWithUnderscoresStrategy {
        public String translate(String in) {
            return (in.toUpperCase().equals(in) ? in : super.translate(in));
        }
    }

    public static class A {
        private String testField;
        public String getTestField() {
            return testField;
        }
        public void setTestField(String field) {
            this.testField = field;
        }
        @JsonProperty("TEST_FIELD")
        public void setFieldAlternate(String field) {
            this.testField = field;
        }
    }

    @Test
    public void something() throws Exception {
        A test = new A();
        test.setTestField("test");
        ObjectMapper mapper = new ObjectMapper().setPropertyNamingStrategy(new CaseInsensitive());
        assertEquals("{\"test_field\":\"test\"}", mapper.writeValueAsString(test));
        assertEquals("test", mapper.readValue("{\"test_field\":\"test\"}", A.class).getTestField());
        assertEquals("test", mapper.readValue("{\"TEST_FIELD\":\"test\"}", A.class).getTestField());
    }
}

. Это более идеально, чем предыдущее решение., но для каждого поля потребуется два аннотированных сеттера -, один для нового формата, другой для поддержки устаревшего формата.

Кто-нибудь сталкивался со способом сделать Джексона нечувствительным к регистру-для десериализации имен полей,или в этом отношении принять несколько псевдонимов для имени поля?

11
задан Dan Watt 10 April 2012 в 01:58
поделиться