This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2024-04-28
Channels
- # announcements (2)
- # babashka (21)
- # beginners (24)
- # calva (9)
- # cider (7)
- # clj-kondo (12)
- # clojure (116)
- # clojure-europe (5)
- # clojure-korea (2)
- # clojure-norway (3)
- # clojure-poland (1)
- # clojure-spec (5)
- # clojurescript (12)
- # cursive (12)
- # datomic (8)
- # google-cloud (4)
- # honeysql (16)
- # java (18)
- # lsp (10)
- # missionary (14)
- # polylith (12)
- # re-frame (13)
- # releases (4)
- # shadow-cljs (10)
- # sql (10)
- # testify (2)
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.> 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?
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?
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