Джексон JSON пользовательская сериализация для определенных полей


есть ли способ использовать процессор Jackson JSON для сериализации пользовательского уровня поля? Например, я хотел бы иметь класс

public class Person {
    public String name;
    public int age;
    public int favoriteNumber;
}

сериализуется в следующий JSON:

{ "name": "Joe", "age": 25, "favoriteNumber": "123" }

обратите внимание, что возраст=25 кодируется как в то время как favoriteNumber=123 кодируется как строка. Из коробки Джексон маршаллс int в число. В этом случае я хочу, чтобы favoriteNumber был закодирован как строка.

5 69

5 ответов:

вы можете реализовать пользовательский сериализатор следующим образом:

public class Person {
    public String name;
    public int age;
    @JsonSerialize(using = IntToStringSerializer.class, as=String.class)
    public int favoriteNumber:
}


public class IntToStringSerializer extends JsonSerializer<Integer> {

    @Override
    public void serialize(Integer tmpInt, 
                          JsonGenerator jsonGenerator, 
                          SerializerProvider serializerProvider) 
                          throws IOException, JsonProcessingException {
        jsonGenerator.writeObject(tmpInt.toString());
    }
}

Java должен обрабатывать автобоксинг от int to Integer для вас.

Jackson-databind (по крайней мере 2.1.3) предоставляет специальные ToStringSerializer (com.fasterxml.jackson.databind.ser.std.ToStringSerializer)

пример:

public class Person {
    public String name;
    public int age;
    @JsonSerialize(using = ToStringSerializer.class)
    public int favoriteNumber:
}

добавить @JsonProperty аннотированный геттер, который возвращает String на

Джексон-аннотации предоставляет @JsonFormat который может обрабатывать множество настроек без необходимости писать пользовательский сериализатор.

например, запрос STRING форма для поля с числовым типом выведет числовое значение в виде строки

public class Person {
    public String name;
    public int age;
    @JsonFormat(shape = JsonFormat.Shape.STRING)
    public int favoriteNumber;
}

приведет к желаемому результату

{"name":"Joe","age":25,"favoriteNumber":"123"}

С помощью @JsonView мы можем решить поля классов моделей для сериализации, которые удовлетворяют минимальным критериям (мы должны определить критерии), как мы можем иметь один основной класс с 10 свойствами, но только 5 свойств могут быть сериализованы, которые необходимы только для клиента

определите наши взгляды, просто создав следующий класс:

public class Views
{
    static class Android{};
    static class IOS{};
    static class Web{};
}

аннотированный класс модели с представлениями:

public class Demo 
{
    public Demo() 
    {
    }

@JsonView(Views.IOS.class)
private String iosField;

@JsonView(Views.Android.class)
private String androidField;

@JsonView(Views.Web.class)
private String webField;

 // getters/setters
...
..
}

теперь мы должны написать пользовательский конвертер json просто расширяя класс HttpMessageConverter от spring как:

    public class CustomJacksonConverter implements HttpMessageConverter<Object> 
    {
    public CustomJacksonConverter() 
        {
            super();
        //this.delegate.getObjectMapper().setConfig(this.delegate.getObjectMapper().getSerializationConfig().withView(Views.ClientView.class));
        this.delegate.getObjectMapper().configure(MapperFeature.DEFAULT_VIEW_INCLUSION, true);
        this.delegate.getObjectMapper().setSerializationInclusion(Include.NON_NULL);

    }

    // a real message converter that will respond to methods and do the actual work
    private MappingJackson2HttpMessageConverter delegate = new MappingJackson2HttpMessageConverter();

    @Override
    public boolean canRead(Class<?> clazz, MediaType mediaType) {
        return delegate.canRead(clazz, mediaType);
    }

    @Override
    public boolean canWrite(Class<?> clazz, MediaType mediaType) {
        return delegate.canWrite(clazz, mediaType);
    }

    @Override
    public List<MediaType> getSupportedMediaTypes() {
        return delegate.getSupportedMediaTypes();
    }

    @Override
    public Object read(Class<? extends Object> clazz,
            HttpInputMessage inputMessage) throws IOException,
            HttpMessageNotReadableException {
        return delegate.read(clazz, inputMessage);
    }

    @Override
    public void write(Object obj, MediaType contentType, HttpOutputMessage outputMessage) throws IOException, HttpMessageNotWritableException 
    {
        synchronized(this) 
        {
            String userAgent = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest().getHeader("userAgent");
            if ( userAgent != null ) 
            {
                switch (userAgent) 
                {
                case "IOS" :
                    this.delegate.getObjectMapper().setConfig(this.delegate.getObjectMapper().getSerializationConfig().withView(Views.IOS.class));
                    break;
                case "Android" :
                    this.delegate.getObjectMapper().setConfig(this.delegate.getObjectMapper().getSerializationConfig().withView(Views.Android.class));
                    break;
                case "Web" :
                    this.delegate.getObjectMapper().setConfig(this.delegate.getObjectMapper().getSerializationConfig().withView( Views.Web.class));
                    break;
                default:
                    this.delegate.getObjectMapper().setConfig(this.delegate.getObjectMapper().getSerializationConfig().withView( null ));
                    break;
                }
            }
            else
            {
                // reset to default view
                this.delegate.getObjectMapper().setConfig(this.delegate.getObjectMapper().getSerializationConfig().withView( null ));
            }
            delegate.write(obj, contentType, outputMessage);
        }
    }

}

теперь нужно сказать spring, чтобы использовать это пользовательское преобразование json, просто поместив это в dispatcher-servlet.xml

<mvc:annotation-driven>
        <mvc:message-converters register-defaults="true">
            <bean id="jsonConverter" class="com.mactores.org.CustomJacksonConverter" >
            </bean>
        </mvc:message-converters>
    </mvc:annotation-driven>

вот как вы сможете решить, какие поля для сериализации.