Anyone here have deep knowledge of Jackson and defining custom serialization? I'm trying to write a serializer that will use the IKVReduce interface but I have no idea how to approach the problem correctly and efficiently.
For example, I tried extending StdSerializer<IKVReduce>, and tried to have private members
private JsonSerializer<Object> _keySer;
private JsonSerializer<Object> _valSer;
But I have no idea how to lazily initialize them at runtime or do it correctly. I want to avoid calls to find the serializer at runtime.I don't think i have deep knowledge
but can you give a little context
are you writing this in Java, clojure with gen-class, or...
> But I have no idea how to lazily initialize them at runtime or do it correctly. I want to avoid calls to find the serializer at runtime. Why do you want lazy initialization exactly?
and the mechanism to use here is jackson modules - making a serializer is part of that though
For bit more context - I'm trying to add a custom serializer for IKVReduce to Jsonista, so it'll be a serializer registered on an ObjectMapper
merging into Jsonista proper, implementing in your own project, or making a new side library?
Ideally merging into jsonista
okay
so what is the reason for lazy initialization? + what do you think should be lazily initialized
I'll just paste my implementation so it'll be easier to discuss:
package jsonista.jackson;
import clojure.lang.AFn;
import clojure.lang.IKVReduce;
import clojure.lang.Util;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.*;
import com.fasterxml.jackson.databind.ser.ContextualSerializer;
import com.fasterxml.jackson.databind.ser.std.StdSerializer;
import java.io.IOException;
import java.util.Map;
public class KVReduceSerializer extends StdSerializer<IKVReduce> implements ContextualSerializer {
private JsonSerializer<Object> _keySer;
private JsonSerializer<Object> _valSer;
public KVReduceSerializer(JsonSerializer<Object> keySer, JsonSerializer<Object> valSer) {
this();
_keySer = keySer;
_valSer = valSer;
}
public KVReduceSerializer() {super (IKVReduce.class);}
protected KVReduceSerializer(Class<IKVReduce> t) {
super(t);
}
protected KVReduceSerializer withResolved(JsonSerializer<Object> keySer, JsonSerializer<Object> valSer) {
return this._keySer == keySer && this._valSer == valSer ? this : new KVReduceSerializer(keySer, valSer);
}
@Override
public JsonSerializer<?> createContextual(SerializerProvider serializerProvider, BeanProperty beanProperty) throws JsonMappingException {
JavaType object = serializerProvider.constructType(Object.class);
JsonSerializer<Object> keySer = serializerProvider.findKeySerializer(object, null);
JsonSerializer<Object> valSer = serializerProvider.findValueSerializer(object);
return this.withResolved(keySer, valSer);
}
private class RFn extends AFn {
// public boolean first;
private final JsonGenerator jsonGenerator;
private final SerializerProvider serializerProvider;
private RFn(JsonGenerator jsonGenerator, SerializerProvider serializerProvider) {
this.jsonGenerator = jsonGenerator;
this.serializerProvider = serializerProvider;
}
public Object invoke(Object b, Object k, Object v) {
try {
_keySer.serialize(k, jsonGenerator, serializerProvider);
_valSer.serialize(v, jsonGenerator, serializerProvider);
} catch (IOException e) {
Util.sneakyThrow(e);
}
return null;
};
}
private void serializeFields(
IKVReduce kv,
JsonGenerator jsonGenerator,
SerializerProvider serializerProvider) {
RFn kvrf = new RFn(jsonGenerator, serializerProvider);
kv.kvreduce(kvrf, null);
}
@Override
public void serialize(IKVReduce stringObjectMap, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {
jsonGenerator.writeStartObject();
serializeFields(stringObjectMap, jsonGenerator, serializerProvider);
jsonGenerator.writeEndObject();
}
}
I was trying to implement the "inverse" of the persistent hash map deserializer, also drew inspiration from the MapSerializer in Jackson Databind
with a debugger on, I can see I go through the createContextual method, but I'm not initializing the value serializer correctly. Ideas?
sorry i've been dragged into stuff; havent had time yet
the one time i've done a jackson module is this
This is as far as I got. I know my code goes through resolve and createContextual (checked with debugger), but I can't figure out how to initialize the serializers correctly.
Eternal glory to whoever solves this