Как указать Джексону использовать только поля - желательно глобально

Поведение jackon по умолчанию, похоже, использует как свойства (геттеры и сеттеры), так и поля для сериализации и десериализации в json.

Я хотел бы использовать поля в качестве канонического источника конфигурации сериализации и, таким образом, не хочу, чтобы Джексон вообще смотрел на свойства.

Я могу сделать это для индивидуального класса с аннотацией:

 @JsonAutoDetect(fieldVisibility = Visibility.ANY, getterVisibility = Visibility.NONE, setterVisibility = Visibility.NONE)

Но я не хочу помещать это в каждый класс ...

Можно ли это настроить глобально? Хотите добавить что-нибудь в Object Mapper?


person Michael Wiles    schedule 18.08.2011    source источник
comment
Тим дал хороший ответ. Другая возможность состоит в том, что если у вас есть общий базовый класс, вы можете добавить к нему аннотации классов; аннотации унаследованы Джексоном.   -  person StaxMan    schedule 18.08.2011
comment
Думаю, я пробовал это, но, похоже, вы должны указать подклассам, чтобы они использовали то, что определяет базовый случай ...   -  person Michael Wiles    schedule 19.08.2011
comment
Нет, если подкласс не переопределяет аннотацию класса, родительские аннотации видны, как если бы они были частью определения подкласса (в противном случае это было бы ошибкой). Это не обязательно то, как JDK работает с аннотациями, но Джексон реализует полное наследование для аннотаций (даже для аннотаций методов).   -  person StaxMan    schedule 19.08.2011
comment
Остерегайтесь флага INFER_PROPERTY_MUTATORS. Он обеспечивает видимость сеттеров, если есть видимый геттер или поле.   -  person Ondra Žižka    schedule 18.06.2018
comment
И другие.   -  person Ondra Žižka    schedule 18.06.2018


Ответы (8)


Вы можете настроить отдельные ObjectMappers следующим образом:

ObjectMapper mapper  = new ObjectMapper();
mapper.setVisibility(mapper.getSerializationConfig().getDefaultVisibilityChecker()
                .withFieldVisibility(JsonAutoDetect.Visibility.ANY)
                .withGetterVisibility(JsonAutoDetect.Visibility.NONE)
                .withSetterVisibility(JsonAutoDetect.Visibility.NONE)
                .withCreatorVisibility(JsonAutoDetect.Visibility.NONE));

Если вы хотите установить его глобально, я обычно обращаюсь к настроенному сопоставителю через класс-оболочку.

person Tim Helmstedt    schedule 18.08.2011
comment
Хорошо, хотя я думаю, что вам может потребоваться также установить средство проверки (методы withXxx () обычно создают новый объект). Что-то вроде 'mapper.setVisibilityChecker (mapper.getVisibilityChecker (). With ...);' - person StaxMan; 18.08.2011
comment
@StaxMan хороший звонок по setVisibilityChecker, я отредактировал ответ, чтобы отразить. - person Kevin Bowersox; 29.09.2011
comment
withGetterVisibility не охватывает is* методы, но есть withIsGetterVisibility для них. - person qerub; 12.05.2012
comment
setVisibilityChecker устарел. Вместо этого используйте setVisibility. - person 0x7d7b; 06.04.2016
comment
Это как раз то, что мне нужно! Эта конфигурация позволила мне использовать Mixin для простого преобразования сущностей Hibernate в DTO. По умолчанию ObjectMapper сериализует все, и Mixin должен указать, какие свойства игнорировать (т.е. вычитание вместо пересечения). - person TastyWheat; 03.06.2019

В Jackson 2.0 и более поздних версиях вы можете просто использовать:

import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;   

...

ObjectMapper mapper = new ObjectMapper();    
mapper.setVisibility(PropertyAccessor.ALL, Visibility.NONE);
mapper.setVisibility(PropertyAccessor.FIELD, Visibility.ANY);

чтобы отключить автоопределение.

person lukk    schedule 21.11.2012
comment
Привет, ребята, я использую банку Jackson 1.9.0. Я получаю дополнительное свойство json при сериализации объекта в строку json. Мне нужно получить строку json, которая содержит только упомянутые переменные с @JsonProperty. Не могли бы вы мне помочь? - person jrhamza; 24.11.2013
comment
Вы можете начать с аннотации класса, упомянутой в вопросе OP: @JsonAutoDetect(fieldVisibility = Visibility.NONE, getterVisibility = Visibility.NONE, setterVisibility = Visibility.NONE) Затем вы должны аннотировать каждое свойство, которое хотите включить, с помощью @JsonProperty - person lukk; 25.11.2013
comment
Спасибо! Раньше я находил много примеров кода, в которых использовался JsonMethod вместо PropertyAccessor. Если вы ищете JsonMethod, вы редко получаете ссылки на PropertyAccessor, тогда ... Как лучше всего найти заменяющие имена классов в артефактах-преемниках? Могут быть жесткими и противными, не так ли? - person philburns; 26.03.2019

Специально для boolean is*() геттеров:

Я потратил много времени на то, почему ни один ниже

  @JsonAutoDetect(fieldVisibility = Visibility.ANY, getterVisibility = Visibility.NONE, setterVisibility = Visibility.NONE)

ни это

  setVisibility(PropertyAccessor.SETTER, JsonAutoDetect.Visibility.NONE);
  setVisibility(PropertyAccessor.GETTER, JsonAutoDetect.Visibility.NONE);
  setVisibility(PropertyAccessor.FIELD, JsonAutoDetect.Visibility.ANY);

работал с моим логическим геттером / сеттером.

Решение простое:

  @JsonAutoDetect(isGetterVisibility = Visibility.NONE, ...          
  setVisibility(PropertyAccessor.IS_GETTER, JsonAutoDetect.Visibility.NONE);

ОБНОВЛЕНИЕ: Spring-boot позволил настроить его:

jackson:
  visibility.field: any
  visibility.getter: none
  visibility.setter: none
  visibility.is-getter: none

См. Общие свойства приложения # JACKSON

person Grigory Kislin    schedule 20.07.2014
comment
Не могли бы вы объяснить, как простое решение следует применить к классу bean-компонентов? - person Pavel Niedoba; 18.03.2016
comment
Спасибо. То есть Getter спас мне день. - person grinch; 04.03.2017
comment
Это не ответ на вопрос и скорее вводит в заблуждение. - person Ondra Žižka; 18.06.2018

для jackson 1.9.10 использую

ObjectMapper mapper = new ObjectMapper();

mapper.setVisibility(JsonMethod.ALL, Visibility.NONE);
mapper.setVisibility(JsonMethod.FIELD, Visibility.ANY);

включить автоопределение.

person mfe    schedule 27.02.2014
comment
Это способ. Спасибо. - person cuneytykaya; 27.02.2014
comment
Интересно, есть ли разница между этим и отключением автоматического обнаружения. - person xenoterracide; 28.01.2016

Как насчет этого: я использовал его с миксином

несоответствующий объект

@Entity
@Getter
@NoArgsConstructor
public class Telemetry {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long pk;
    private String id;
    private String organizationId;
    private String baseType;
    private String name;
    private Double lat;
    private Double lon;
    private Instant updateTimestamp;
}

Mixin:

@JsonAutoDetect(fieldVisibility = ANY, getterVisibility = NONE, setterVisibility = NONE)
public static class TelemetryMixin {}

Использование:

    ObjectMapper om = objectMapper.addMixIn(Telemetry.class, TelemetryMixin.class);
    Telemetry[] telemetries = om.readValue(someJson, Telemetry[].class);

Нет ничего, что говорило бы о том, что вы не можете использовать любое количество классов и применить один и тот же миксин.

Если вы не знакомы с миксинами, они концептуально просты: структура миксина наложена на целевой класс (согласно Джексону, но не в том, что касается JVM).

person Christian Bongiorno    schedule 21.12.2016

Если вам нужен способ сделать это глобально, не беспокоясь о конфигурации вашего ObjectMapper, вы можете создать свою собственную аннотацию:

@Target({ElementType.ANNOTATION_TYPE, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@JacksonAnnotationsInside
@JsonAutoDetect(
        getterVisibility = JsonAutoDetect.Visibility.NONE, isGetterVisibility = JsonAutoDetect.Visibility.NONE,
        setterVisibility = JsonAutoDetect.Visibility.NONE, fieldVisibility = JsonAutoDetect.Visibility.NONE,
        creatorVisibility = JsonAutoDetect.Visibility.NONE
)
public @interface JsonExplicit {
}

Теперь вам просто нужно аннотировать свои классы с помощью @JsonExplicit, и все готово!

Также не забудьте отредактировать приведенный выше вызов на @JsonAutoDetect, чтобы убедиться, что у вас установлены значения, которые работают с вашей программой.

Благодарим https://stackoverflow.com/a/13408807 за то, что помогли мне узнать о @JacksonAnnotationsInside

person retodaredevil    schedule 26.12.2019

Если вы используете Spring Boot, вы можете настроить Jackson глобально следующим образом:

import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import org.springframework.boot.autoconfigure.jackson.Jackson2ObjectMapperBuilderCustomizer;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder;

@Configuration
public class JacksonObjectMapperConfiguration implements Jackson2ObjectMapperBuilderCustomizer {

    @Override
    public void customize(Jackson2ObjectMapperBuilder jacksonObjectMapperBuilder) {
        jacksonObjectMapperBuilder.visibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.NONE);
        jacksonObjectMapperBuilder.visibility(PropertyAccessor.FIELD, JsonAutoDetect.Visibility.ANY);
        jacksonObjectMapperBuilder.visibility(PropertyAccessor.CREATOR, JsonAutoDetect.Visibility.ANY);
    }

}

person Times    schedule 15.01.2020

@since 2.10 версию, мы можем использовать JsonMapper.Builder и принятый ответ может выглядеть так:

JsonMapper mapper = JsonMapper.builder()
    .visibility(PropertyAccessor.FIELD, JsonAutoDetect.Visibility.ANY)
    .visibility(PropertyAccessor.GETTER, JsonAutoDetect.Visibility.NONE)
    .visibility(PropertyAccessor.SETTER, JsonAutoDetect.Visibility.NONE)
    .visibility(PropertyAccessor.CREATOR, JsonAutoDetect.Visibility.NONE)
    .build();
person Michał Ziober    schedule 28.10.2020