У меня проблема с сериализацией/десериализацией с 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();
}