@JsonSerialize - Cómo crear un contenedor en tiempo de ejecución y el uso de serialización por defecto para los campos del objeto?

Flyout91:

Quiero añadir un envoltorio que nombró se determina en tiempo de ejecución, ya que depende del nombre de la clase (que podría utilizar @JsonRootName pero yo no quiero porque me gustaría tener que usarlo en cada subclase, que no es eficiente) .

Supongo que debería utilizar @JsonSerializepara anular el serializador predeterminado, pero quiero que se acaba de crear la envoltura; No quiero serializar los campos del objeto mismo (también yo estoy en una clase abstracta, por lo que no sé ni por los campos de la clase sub!). No me importa acerca de ellos, sólo importa el envoltorio! Así que me gustaría que el serializador predeterminado para manejar esos campos para mí, o algo por el estilo.

@JsonSerialize(using = CustomSerializer.class)
public abstract class Request {

    public static class CustomSerializer extends JsonSerializer<Request > {
        @Override
        public void serialize(Request request, JsonGenerator jgen, SerializerProvider provider) throws IOException {
            // Doing my stuff to determine the wrapper name based on request.class.getSimpleName()
            // Then what should I wright to serialize the fields?
            // Basically I just want a function to generate the same json that the default serializer would generate!

            // I tried the following, but obviously it gives a com.fasterxml.jackson.databind.JsonMappingException: Infinite recursion
            jgen.writeObject(value);

            // Same error for the function below 
            provider.defaultSerializeValue(value, jgen);
        }
    }
Michael Ziober:

Para crear serializador envoltorio que necesita para su uso com.fasterxml.jackson.databind.ser.BeanSerializerModifierclase. Puede registrarlo usando com.fasterxml.jackson.databind.module.SimpleModule. A continuación ejemplo muestra de extremo a extremo solución de cómo hacerlo:

import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.BeanDescription;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationConfig;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.json.JsonMapper;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.fasterxml.jackson.databind.ser.BeanSerializerModifier;
import com.fasterxml.jackson.databind.util.NameTransformer;

import java.io.IOException;
import java.util.UUID;

public class JsonPathApp {

    public static void main(String[] args) throws Exception {
        SimpleModule wrappersModule = new SimpleModule("requestWrapper");
        wrappersModule.setSerializerModifier(new BeanSerializerModifier() {
            @Override
            public JsonSerializer<?> modifySerializer(SerializationConfig config, BeanDescription beanDesc, JsonSerializer<?> serializer) {
                if (Request.class.isAssignableFrom(beanDesc.getBeanClass())) {
                    return new RequestWrapperJsonSerializer(serializer);
                }
                return serializer;
            }
        });
        ObjectMapper mapper = JsonMapper.builder()
                .enable(SerializationFeature.INDENT_OUTPUT)
                .addModule(wrappersModule)
                .build();

        System.out.println(mapper.writeValueAsString(new Request1(1, "POST")));
        System.out.println(mapper.writeValueAsString(new Request2(2, UUID.randomUUID())));
    }
}

class RequestWrapperJsonSerializer extends JsonSerializer<Request> {

    private final JsonSerializer baseSerializer;

    public RequestWrapperJsonSerializer(JsonSerializer baseSerializer) {
        this.baseSerializer = baseSerializer;
    }

    @Override
    public void serialize(Request value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
        gen.writeStartObject();
        gen.writeFieldName(value.getClass().getSimpleName() + "Wrapper");
        gen.writeStartObject();
        baseSerializer.unwrappingSerializer(NameTransformer.NOP).serialize(value, gen, serializers);
        gen.writeEndObject();
        gen.writeEndObject();
    }
}

abstract class Request {
    private int id;

    //constructor, getters, setters, toString
}

class Request1 extends Request {
    private String body;

    //constructor, getters, setters, toString
}

class Request2 extends Request {

    private UUID uuid;

    //constructor, getters, setters, toString
}

imprime el código de seguridad:

{
  "Request1Wrapper" : {
    "id" : 1,
    "body" : "POST"
  }
}
{
  "Request2Wrapper" : {
    "id" : 2,
    "uuid" : "dd4cccb5-1cf5-4dd4-8bc7-97cb101e5d7d"
  }
}

En lugar unwrappingSerializermétodo que puede utilizar serializeel método de embalaje y retire las invocaciones adicionales.

Supongo que te gusta

Origin http://43.154.161.224:23101/article/api/json?id=363062&siteId=1
Recomendado
Clasificación