Skip to content

Instantly share code, notes, and snippets.

@nithril
Created July 19, 2022 19:42
Show Gist options
  • Save nithril/b55d6ab32db253dfe24995f87c899685 to your computer and use it in GitHub Desktop.
Save nithril/b55d6ab32db253dfe24995f87c899685 to your computer and use it in GitHub Desktop.
private final BeanIdResolver resolver = new BeanIdResolver();
private final String propertyName = resolver.getMechanism().getDefaultPropertyName();
@Override
public Object deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
var mapper = (ObjectMapper) p.getCodec();
var treeNode = mapper.readTree(p);
// Primitive
if (treeNode instanceof NumericNode n) {
return switch (n.numberType()) {
case INT, LONG -> n.asLong();
case BIG_INTEGER -> n.bigIntegerValue();
case FLOAT, DOUBLE -> n.asDouble();
case BIG_DECIMAL -> n.decimalValue();
};
} else if (treeNode instanceof TextNode t) {
return t.asText();
} else if (treeNode instanceof BooleanNode b) {
return b.asBoolean();
} else if (treeNode instanceof ArrayNode a) {
if (a.isEmpty()) {
return List.of();
}
if (a.get(0).isValueNode() || a.get(0).isArray()) {
// collection of primitive or collection of collection of all but pojo
return mapper.treeToValue(treeNode, List.class);
} else {
// Get the type
var type = Streams.stream(a)
.map(o -> ((ObjectNode) o).remove(propertyName).asText())
.reduce((l, r) -> l)
.get(); // Array cannot be empty
var javaType = resolver.typeFromId(ctxt, type);
var collectionType = ctxt.getTypeFactory().constructCollectionType(List.class, javaType);
return mapper.treeToValue(treeNode, collectionType);
}
} else if (treeNode instanceof ObjectNode o) {
// Pojo, map is not supported (yet)
var javaType = resolver.typeFromId(ctxt, o.get(propertyName).textValue());
o.remove(propertyName);
return mapper.treeToValue(treeNode, javaType);
} else {
throw new RuntimeException("Unsupported node %s".formatted(treeNode));
}
}
private final BeanIdResolver idResolver = new BeanIdResolver();
private final String propertyName = idResolver.getMechanism().getDefaultPropertyName();
public AsPropertyTypeSerializer asPropertyTypeSerializer = new AsPropertyTypeSerializer(idResolver, null, propertyName);
public void serialize(Object value, JsonGenerator gen, SerializerProvider provider) throws IOException {
var map = (Map<String, Object>) value;
for (var e : map.entrySet()) {
gen.writeFieldName(e.getKey());
if (isPrimitive(e.getValue())) {
gen.getCodec().writeValue(gen, e.getValue());
} else if (e.getValue() instanceof Collection c) {
serializeCollection(gen, provider, c);
} else {
provider.findValueSerializer(e.getValue().getClass()).serializeWithType(e.getValue(), gen, provider, asPropertyTypeSerializer);
}
}
}
private void serializeCollection(JsonGenerator gen, SerializerProvider provider, Collection col) throws IOException {
var firstValue = firstNonNullValue(col);
if (col.isEmpty() || firstValue.isEmpty()) {
gen.writeStartArray();
gen.writeEndArray();
} else {
if (isPrimitive(firstValue.get()) || firstValue.get() instanceof Collection) {
// collection of primitive or collection of collection of all but pojo
gen.getCodec().writeValue(gen, col);
} else {
// Collection of pojo
// Assuming consistent type over the collection, any type for pojo is not supported and not desired
// Polymorphism is not supported
var javaType = provider.getTypeFactory().constructType(firstValue.get().getClass());
var valueSerializer = provider.findValueSerializer(javaType);
if (col instanceof List) {
new IndexedListSerializer(javaType, false, asPropertyTypeSerializer, valueSerializer)
.serialize((List) col, gen, provider);
} else {
new CollectionSerializer(javaType, false, asPropertyTypeSerializer, valueSerializer)
.serialize(col, gen, provider);
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment