Джексон преодолевает подчеркивание в пользу верблюжьего чехла

160

Я получаю строку JSON из Интернета; как и большинство JSON, которые я видел, он содержит длинные ключи, разделенные подчеркиванием. По сути, моя цель - десериализовать JSON в java-объекты, но я не использую подчеркивания в java-коде.

Например, у меня может быть Userкласс с firstNameполем в случае верблюда, одновременно мне нужно как-то сказать Джексону сопоставить first_nameключ из JSON в firstNameполе класса. Является ли это возможным?

class User{
    protected String firstName;
    protected String getFirstName(){return firstName;}
}
user1384991
источник

Ответы:

104

Вы должны использовать @JsonPropertyполе, в котором вы хотите изменить отображение имен по умолчанию.

class User{
    @JsonProperty("first_name")
    protected String firstName;
    protected String getFirstName(){return firstName;}
}

Для получения дополнительной информации: API

Alex
источник
86
Не делайте этого, иначе вам придется делать это для каждой собственности. Смотрите ответ thehpi ниже.
Райан Шиллингтон
Я смог аннотировать только одно свойство, но оно изменило порядок свойств в сгенерированной строке: аннотированные свойства появились последними. (Джексон 2.3.0)
eebbesen
1
@RyanShillington - Поправьте меня, если я ошибаюсь, но это единственный вариант, если строка JSON, с которой вы выполняете синтаксический анализ, не использует согласованный формат, т. Е. Использует и camelCase, и подчеркивание?
DavidR
@DavidR Это правильно. Я предполагаю, что вы не можете исправить исходные данные? Это отстой.
Райан Шиллингтон
@PaulTsai хорошо, так что не стесняйтесь использовать их :)
Alex
351

Вы можете настроить ObjectMapperпреобразование регистра верблюда в имена с подчеркиванием:

objectMapper.setPropertyNamingStrategy(PropertyNamingStrategy.SNAKE_CASE);

Или аннотируйте определенный класс модели этой аннотацией:

@JsonNaming(PropertyNamingStrategy.SnakeCaseStrategy.class)

До Джексона 2.7 константа называлась:

PropertyNamingStrategy.CAMEL_CASE_TO_LOWER_CASE_WITH_UNDERSCORES
thehpi
источник
5
Обратите внимание, что это было введено только в Jackson 1.9.
Дэвид Моулз
62
@deprecated С версии 2.7 вместо этого используйте SNAKE_CASE;
Thermech
1
один вопрос: когда я использую стратегию именования snake_case, файлы json с подчеркиванием будут десериализованы для случая верблюда?
Рам Патра
2
@Ramswaroop Да, это заставляет Джексона и говорить, и ожидать snake_case
Дрю Стивенс
1
@Ramswaroop Для меня с Jackson 2.7.3 и свойствами, помеченными просто @JsonProperty(имя, выведенное из нормальных camelCaseсвойств Java), PropertyNamingStrategy.SNAKE_CASEдесериализация перестала работать с camelCase JSON (как я использовал) и потребовала snake_case.
Дрю Стивенс
119

Если это весеннее загрузочное приложение, в файле application.properties просто используйте

spring.jackson.property именования-стратегия = SNAKE_CASE

Или Аннотируйте класс модели с этой аннотацией.

@JsonNaming (PropertyNamingStrategy.SnakeCaseStrategy.class)

adam.smithsonian01
источник
3
Если я аннотирую свой класс с помощью «@JsonNaming (PropertyNamingStrategy.SnakeCaseStrategy.class)», это работает. Но если я использую "spring.jackson.property-naming-стратегии = SNAKE_CASE" в "application.properties", это не будет. Я использую "Spring Boot (v2.0.0.BUILD-SNAPSHOT)". У тебя есть идеи ?
Бруно
1
то же самое здесь, spring.jackson.property-naming-strategy=SNAKE_CASEне работает, я использую Spring Boot 2.0
soulmachine
1
то же самое здесь, spring.jackson.property-naming-стратегии = SNAKE_CASE не работает, я использую Spring Boot 2.0.5. Но использование аннотации работает для меня
Нео Фам
Может быть, ваш ObjectMapperне создан Spring? Создайте класс @Configuration с помощью метода @Bean, который возвращает ObjectMapper. Не уверен, если это необходимо.
Ондра Жижка
48

Если вы хотите это для одного класса, вы можете использовать PropertyNamingStrategy с @JsonNaming , что-то вроде этого:

@JsonNaming(PropertyNamingStrategy.LowerCaseWithUnderscoresStrategy.class)
public static class Request {

    String businessName;
    String businessLegalName;

}

Будет сериализовать в:

{
    "business_name" : "",
    "business_legal_name" : ""
}

Поскольку в осуждается в пользу , так что вы должны использовать:Jackson 2.7LowerCaseWithUnderscoresStrategySnakeCaseStrategy

@JsonNaming(PropertyNamingStrategy.SnakeCaseStrategy.class)
public static class Request {

    String businessName;
    String businessLegalName;

}
Артуро Вольпе
источник
29

Приведенные выше ответы касаются @JsonPropertyи CAMEL_CASE_TO_LOWER_CASE_WITH_UNDERSCORESявляются точными на 100%, хотя некоторые люди (например, я) могут попытаться сделать это в приложении Spring MVC с конфигурацией на основе кода. Вот пример кода (который у меня внутри Beans.java) для достижения желаемого эффекта:

@Bean
public ObjectMapper jacksonObjectMapper() {
    return new ObjectMapper().setPropertyNamingStrategy(
            PropertyNamingStrategy.CAMEL_CASE_TO_LOWER_CASE_WITH_UNDERSCORES);
}
Dawngerpony
источник
9
Альтернатива Spring Boot, если вы используете Spring Boot <= 1.3, в application.propertiesadd spring.jackson.property-naming-strategy=CAMEL_CASE_TO_LOWER_CASE_WITH_UNDERSCOR‌​ES. Для Spring Boot 1.4 используйте spring.jackson.property-naming-strategy=SNAKE_CASEвместо этого.
торт с
1
@zapl да, вы правы, я, вероятно, упомянул версию Джексона вместо версии Spring-Boot. Позвольте мне удалить этот комментарий, чтобы избежать путаницы.
Рам Патра
1
Начиная с версии 2.7 Джексона это SNAKE_CASE. Это сработало для меня: final ObjectMapper objectMapper = new ObjectMapper().setPropertyNamingStrategy( PropertyNamingStrategy.SNAKE_CASE);
Джонатан
12

В настоящее время рекомендуется настроить Джексона в файле application.yml(или properties).

Пример:

spring:
  jackson:
    property-naming-strategy: SNAKE_CASE

Если у вас есть более сложные требования к конфигурации, вы также можете настроить Джексона программно.

import com.fasterxml.jackson.databind.PropertyNamingStrategy;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder;

@Configuration
public class JacksonConfiguration {

    @Bean
    public Jackson2ObjectMapperBuilder jackson2ObjectMapperBuilder() {
        return new Jackson2ObjectMapperBuilder()
                .propertyNamingStrategy(PropertyNamingStrategy.SNAKE_CASE);
        // insert other configurations
    }

} 
Кенни Кейсон
источник
Знаете ли вы, если у вас есть другой экземпляр jackson2objectmapper, загружаемый и переопределяющий этот? И можете ли вы подтвердить, что даже этот бин загружается?
Кенни Кейсон
Также приведите решение DuffJ в движение. Это довольно похоже.
Кенни Кейсон
Я думаю, что настройка свойств - правильный путь; и рекомендуется тоже. Это так же, как это.
WesternGun
@WesternGun хороший звонок. Я стараюсь делать это через yaml / properties, когда это возможно.
Кенни Кейсон
6

Ниже приведено несколько ответов, указывающих обе стратегии для двух разных версий библиотеки Джексона:

Для Джексона 2.6. *

ObjectMapper objMapper = new ObjectMapper(new JsonFactory()); // or YAMLFactory()
objMapper.setNamingStrategy(
     PropertyNamingStrategy.CAMEL_CASE_TO_LOWER_CASE_WITH_UNDERSCORES);

Для Джексона 2.7. *

ObjectMapper objMapper = new ObjectMapper(new JsonFactory()); // or YAMLFactory()
objMapper.setNamingStrategy(
     PropertyNamingStrategy.SNAKE_CASE);
Амит Канерия
источник
снова они устарели некоторые значения, теперь у них есть KEBAB_CASE, ням!
Kalpesh Soni
FTR: чехол для кебаба - не змеиный ;-)
Рене