2016-03-29 2 views
2

Я хочу, чтобы оба использовали пользовательский сериализатор и имели обозначение JsonInclude.Include.NON_DEFAULT. Когда я не использую собственный сериализатор, он соблюдается, но когда я использую собственный сериализатор, это не так.JsonInclude.Include.NON_DEFAULT не работает с пользовательским сериализатором

Это Джексон 2.2.2. В настоящее время у меня нет возможности перейти на более новую версию Jackson.

Вот простой пример, который показывает проблему:

import com.fasterxml.jackson.annotation.JsonGetter; 
import com.fasterxml.jackson.annotation.JsonInclude; 
import com.fasterxml.jackson.core.JsonGenerator; 
import com.fasterxml.jackson.databind.JsonSerializer; 
import com.fasterxml.jackson.databind.ObjectMapper; 
import com.fasterxml.jackson.databind.SerializerProvider; 
import com.fasterxml.jackson.databind.annotation.JsonSerialize; 

import java.io.IOException; 
import java.util.EnumSet; 
import java.util.Set; 
import java.util.stream.Collectors;  

public class JacksonSerialization 
{ 
    public static void main(String[] args) throws Exception { 
     ObjectMapper serializer = new ObjectMapper(); 

     Foo foo = new Foo(); 
     foo.setFlags(EnumSet.of(Flag.CC, Flag.BB)); 
     System.out.println(serializer.writeValueAsString(foo)); 

     foo = new Foo(); 
     System.out.println(serializer.writeValueAsString(foo)); 
    } 

    public static enum Flag 
    { 
     AA, 
     BB, 
     CC 
    } 

    @JsonInclude(JsonInclude.Include.NON_DEFAULT) 
    public static class Foo 
    { 
     private Set<Flag> flags; 

     public Foo() { 
      flags = EnumSet.of(Flag.AA); 
     } 

     @JsonGetter("f") 
     @JsonSerialize(using = FlagSetSerializer.class) 
     public Set<Flag> getFlags() { 
      return flags; 
     } 

     public void setFlags(Set<Flag> theFlags) { 
      flags = theFlags; 
     } 
    } 

    public static class FlagSetSerializer extends JsonSerializer<Set<Flag>> 
    { 
     @Override 
     public void serialize(Set<Flag> value, 
           JsonGenerator jsonGenerator, 
           SerializerProvider serializerProvider) throws IOException { 
      String csv = value.stream() 
        .map(Flag::toString) 
        .collect(Collectors.joining(",")); 
      jsonGenerator.writeString(csv); 
     } 
    } 
} 

И вот результат:

{"f":"BB,CC"} 
{"f":"AA"} 

Обратите внимание, что f в сериализации, даже если он имеет значение по умолчанию. Если я закомментируйте @JsonSerialize аннотацию, то я получаю следующий вывод:

{"f":["BB","CC"]} 
{} 

Тогда f правильно делает не получить сериализации. Но, конечно, вещи не сериализуются в формате, который я хочу.

Как я могу получить пользовательский сериализатор, чтобы почтить аннотацию @JsonInclude класса?

ответ

2

Вы, вероятно, хотите реализовать public boolean isEmpty(SerializerProvider provider, T value) согласно documentation, в котором говорится:

общественного логический IsEmpty (поставщик SerializerProvider, значение T)

метод называется, чтобы проверить, является ли считать данный сериализации значение " пустое "значение (для подавления сериализации пустых значений ).

Реализация по умолчанию будет учитывать только нулевые значения: пусто.

По https://github.com/FasterXML/jackson-databind/issues/730

Другим возможным источником проблемы является то, что вы говорите о NON_EMPTY но код использует NON_DEFAULT.


И скорее слишком много копаться в отладчике приводит меня предложить

@JsonSerialize(using = FlagSetSerializer.class, include = JsonSerialize.Inclusion.NON_DEFAULT)

который, кажется, проходят тесты.

проблема, кажется, в JacksonAnnotationInspector#findSerializationInclusion, который сначала ищет атрибут на свойстве @JsonInclude, и когда он не может найти, что он ищет @JsonSerialize аннотацию. @JsonSerialize содержит устаревшее свойство include, которое имеет значение по умолчанию ALWAYS.

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

+0

Нет метода с этой подписью на 'JsonSerializer'. Кроме того, я спрашиваю о 'NON_DEFAULT', а не' NON_EMPTY'. – QuantumMechanic

+0

Спасибо за примечание NON_EMPTY против NON_DEFAULT. Я отредактировал вопрос, чтобы исправить ошибку в вопросе. – QuantumMechanic

+0

Какую версию Джексона вы используете? Вы можете посмотреть на 'public boolean isEmpty (T value)'. Но все это может не иметь значения, если вы действительно ищете обработку NON_DEFAULT. – ptomli

Смежные вопросы