從json-lib轉成jackson的遇到的問題

輕架構發表於2019-01-10

從json-lib轉成jackson的遇到的問題

問題一:json 字串,再經過Jackson序列化之後就變成原生字串了。而json-lib經過再序列化之後,還是json格式的串。

針對這種情況,可以寫一個Serializer類,遇到json串的時候就當作原生字串寫入即可。

<<JsonStringSerializer>>

 /**
 * 序列化時,對Json格式的字串做特殊處理:不用引號括起來
 * @author
 *
 */
public class JsonStringSerializer extends JsonSerializer<Object> {
    
    @Override
    public void serialize(Object value, JsonGenerator jgen, SerializerProvider provider) throws IOException {
        
        if (value == null) {
            jgen.writeNull();
        } else {
            if (value instanceof String) {
                String newValue = ((String) value).trim();
                // 只對Json格式的字串做處理
                if (newValue.startsWith(“{“) || newValue.startsWith(“[“)) {
                    jgen.writeRawValue((String) value);
                } else {
                    jgen.writeObject(value);
                }
            } else {
                jgen.writeObject(value);
            }
        }
    }
}

 

問題二、jackson和json-lib對null值的處理大不相同。對於值為null的字串型別的欄位,jackson輸出null,而json-lib輸出空字串。對於List型別,json-lib輸出空列表[],而jackson還是輸出null。

如果是從json-lib移植到jackson,為了相容老程式碼,可以寫一個SerializerProvider,遇到null值輸出空字串等。

<<NullToEmptyStringProvider>>

 /**
 * Customize the DefaultSerializerProvider so that when it is looking for a
 * NullSerializer it will use one that is class sensitive, writing strings as “”
 * and everything else using the default value.
 *
 * @author
 */
public class NullToEmptyStringProvider extends DefaultSerializerProvider {

    private static final long serialVersionUID = -1L;

    // A couple of constructors and factory methods to keep the compiler happy
    public NullToEmptyStringProvider() {
        super();
    }

    public NullToEmptyStringProvider(NullToEmptyStringProvider provider, SerializationConfig config,
            SerializerFactory jsf) {
        super(provider, config, jsf);
    }

    @Override
    public NullToEmptyStringProvider createInstance(SerializationConfig config, SerializerFactory jsf) {
        return new NullToEmptyStringProvider(this, config, jsf);
    }

    @Override
    public JsonSerializer<Object> findNullValueSerializer(BeanProperty property) throws JsonMappingException {
        if (property.getType().getRawClass().equals(String.class)) {
            return EmptyStringSerializer.INSTANCE;
        } else if ((property.getType().isArrayType() || property.getType().isCollectionLikeType())
                && !property.getType().isMapLikeType()) {
            return EmptyListSerializer.INSTANCE;
        } else if (property.getType().getRawClass().equals(Long.class)
                || property.getType().getRawClass().equals(Short.class)
                || property.getType().getRawClass().equals(Integer.class)
                || property.getType().getRawClass().equals(Double.class)
                || property.getType().getRawClass().equals(Float.class)
                || property.getType().getRawClass().equals(BigDecimal.class)) {
            return EmptyNumberSerializer.INSTANCE;
        } else {
            return super.findNullValueSerializer(property);
        }
    }
}

/**
 * Output null of String to empty string.
 *
 * @author
 *
 */
class EmptyStringSerializer extends JsonSerializer<Object> {

    public static final JsonSerializer<Object> INSTANCE = new EmptyStringSerializer();

    private EmptyStringSerializer() {
    }

    // Since we know we only get to this seralizer in the case where the value
    // is null and the type is String, we can
    // do our handling without any additional logic and write that empty string
    // we are so desperately wanting.
    @Override
    public void serialize(Object o, JsonGenerator jsonGenerator, SerializerProvider serializerProvider)
            throws IOException {

        jsonGenerator.writeString(“”);
    }
}

/**
 * For null list
 * @author
 *
 */
class EmptyListSerializer extends JsonSerializer<Object> {

    public static final JsonSerializer<Object> INSTANCE = new EmptyListSerializer();

    private EmptyListSerializer() {
    }

    // Since we know we only get to this seralizer in the case where the value
    // is null and the type is String, we can
    // do our handling without any additional logic and write that empty string
    // we are so desperately wanting.
    @Override
    public void serialize(Object o, JsonGenerator jsonGenerator, SerializerProvider serializerProvider)
            throws IOException {
        jsonGenerator.writeStartArray();
        jsonGenerator.writeEndArray();
    }
}

/**
 * For null Number, such as Integer, Long, Short ….
 * @author
 *
 */
class EmptyNumberSerializer extends JsonSerializer<Object> {

    public static final JsonSerializer<Object> INSTANCE = new EmptyNumberSerializer();

    private EmptyNumberSerializer() {
    }

    // Since we know we only get to this seralizer in the case where the value
    // is null and the type is String, we can
    // do our handling without any additional logic and write that empty string
    // we are so desperately wanting.
    @Override
    public void serialize(Object o, JsonGenerator jsonGenerator, SerializerProvider serializerProvider)
            throws IOException {
        jsonGenerator.writeNumber(0);
    }
}

 

最後,需要把這個provider配置到jackson的mapper例項中。

jsonMapper.setSerializerProvider(new NullToEmptyStringProvider());

 

相關文章