我在使用Jackson 1.9.13(和Jackson 2.5.0)进行序列化/反序列化时遇到了问题,现在已经解决了好几天,没有任何成功。

我的目标是使用@JsonAnyGetter和@JsonAnySetter,并且我想动态计算是否应将对象写入输出。我有一个JSON定义,可以使用ObjectMapper进行序列化(并检查是否应包含Object),然后将对象转换回字符串。

我为此使用了“HidableSerializer”,它在序列化过程中可以正常工作,但在将对象转换回字符串时却不能。

没有@JsonAnySetter/-getter 的“HidableSerializer”,一切正常,但不能同时使用。

为什么这不起作用?我该如何解决这个问题呢?欢迎更好的方法!

堆栈跟踪如下所示:

堆栈跟踪

org.codehaus.jackson.map.JsonMappingException: (was java.lang.NullPointerException) (through reference chain: ch.hasselba.Test["[anySetter]"])
null
    at org.codehaus.jackson.map.JsonMappingException.wrapWithPath(JsonMappingException.java:218)
    at org.codehaus.jackson.map.JsonMappingException.wrapWithPath(JsonMappingException.java:183)
    at org.codehaus.jackson.map.ser.std.SerializerBase.wrapAndThrow(SerializerBase.java:140)
    at org.codehaus.jackson.map.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:158)
    at org.codehaus.jackson.map.ser.BeanSerializer.serialize(BeanSerializer.java:112)
at ch.hasselba.HidableSerializer.serialize(HidableSerializer.java:29)
    at org.codehaus.jackson.map.ser.StdSerializerProvider._serializeValue(StdSerializerProvider.java:610)
    at org.codehaus.jackson.map.ser.StdSerializerProvider.serializeValue(StdSerializerProvider.java:256)
    at org.codehaus.jackson.map.ObjectMapper._configAndWriteValue(ObjectMapper.java:2575)
    at org.codehaus.jackson.map.ObjectMapper.writeValueAsString(ObjectMapper.java:2097)
    at ch.hasselba.Demo.main(Demo.java:54)
Caused by: java.lang.NullPointerException
    at org.codehaus.jackson.map.ser.std.MapSerializer.serializeFields(MapSerializer.java:243)
    at org.codehaus.jackson.map.ser.AnyGetterWriter.getAndSerialize(AnyGetterWriter.java:41)
    at org.codehaus.jackson.map.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:154)
    ... 7 more

演示代码
package ch.hasselba;

import org.codehaus.jackson.Version;
import org.codehaus.jackson.map.JsonSerializer;
import org.codehaus.jackson.map.ObjectMapper;
import org.codehaus.jackson.map.SerializationConfig;
import org.codehaus.jackson.map.introspect.BasicBeanDescription;
import org.codehaus.jackson.map.module.SimpleModule;
import org.codehaus.jackson.map.ser.BeanSerializerModifier;

public class Demo {

    public static void main(String[] args) {

        ObjectMapper mapper = new ObjectMapper();

        // register the module
        Version version = new Version(1, 0, 0, "SNAPSHOT");
        mapper.registerModule(new SimpleModule("HidableModule", version) {
            @Override
            public void setupModule(SetupContext context) {
                super.setupModule(context);
                context.addBeanSerializerModifier(new BeanSerializerModifier() {
                    @SuppressWarnings("unchecked")
                    @Override
                    public JsonSerializer<?> modifySerializer(SerializationConfig config, BasicBeanDescription desc,
                        JsonSerializer<?> serializer) {
                        if (IHidable.class.isAssignableFrom(desc.getBeanClass())) {
                            return new HidableSerializer<Object>((JsonSerializer<Object>) serializer);
                        }
                        return serializer;
                    }
                });
            }
        });

        // the data
        String content = "{ \"foo\": \"bar\" }";

        // build the Object
        Test test = null;
        try {
            test =  mapper.readValue(content, Test.class);
        } catch (Exception e) {
            e.printStackTrace();
        }

        // and now convert it back to a String
        String data = null;
        try {
             data = mapper.writeValueAsString(test);
        } catch (Exception e) {
            e.printStackTrace();
        }

        System.out.println( data );

    }

}

测试类
package ch.hasselba;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import org.codehaus.jackson.annotate.JsonAnyGetter;
import org.codehaus.jackson.annotate.JsonAnySetter;

public class Test implements IHidable {

    private Map<String, Object> others = new ConcurrentHashMap<String, Object>();

    @JsonAnyGetter
    public Map<String, Object> getOthers() {
        return this.others;
    }

    @JsonAnySetter
    public void addOther(final String name, final Object value) {
        this.others.put(name, value);
    }

    @Override
    public boolean isHidden() {
        return false;
    }

}

隐藏的序列化程序
package ch.hasselba;

import java.io.IOException;

import org.codehaus.jackson.JsonGenerator;
import org.codehaus.jackson.JsonProcessingException;
import org.codehaus.jackson.map.JsonSerializer;
import org.codehaus.jackson.map.SerializerProvider;

public class HidableSerializer<T> extends JsonSerializer<T> {

    private JsonSerializer<T> defaultSerializer;

    public HidableSerializer(JsonSerializer<T> serializer) {
        defaultSerializer = serializer;
    }

    @Override
    public void serialize(T value, JsonGenerator jgen, SerializerProvider provider)
            throws IOException, JsonProcessingException {

        if( value instanceof IHidable ){
            IHidable hidableValue = (IHidable) value;
            if( hidableValue.isHidden() )
                return;
        }
        defaultSerializer.serialize(value, jgen, provider);

    }

}

IHidableInterface
package ch.hasselba;


public interface IHidable {
    boolean isHidden();
}

最佳答案

问题在于,您在HidableSerializer内使用的defaultSerializer实例是ResolvableSerializer(BeanSerializer),但是当您将它包装到您的ModifySerializer()方法中的JsonSerializer(HidableSerializer)中时,它的resolve()方法就永远不会被调用,并且它无法正确初始化。

如果您尝试将以下行添加到HidableSerializer.serialize()方法中:

...
((ResolvableSerializer)defaultSerializer).resolve(provider);
defaultSerializer.serialize(value, jgen, provider);
...

它应该可以解决问题。

如果这对您有用,那么一个更永久的解决方案是让您的HidableSerializer实现ResolvableSerializer本身,然后将resolve()委托(delegate)给defaultSerializer,如下所示:
@Override
public void resolve(SerializerProvider serializerProvider) throws JsonMappingException {
    if(defaultSerializer instanceof ResolvableSerializer) {
         ((ResolvableSerializer)defaultSerializer).resolve(serializerProvider);
    }
}

10-04 18:06