package com.codepoetics.octarine.json.serialisation; import com.codepoetics.octarine.records.Key; import com.codepoetics.octarine.records.Record; import com.codepoetics.octarine.records.Value; import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.core.Version; import com.fasterxml.jackson.databind.JsonSerializer; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.SerializerProvider; import com.fasterxml.jackson.databind.module.SimpleModule; import java.io.IOException; import java.util.Collection; import java.util.Map; import java.util.stream.Stream; import static com.codepoetics.octarine.Octarine.$$; public class ReflectiveRecordSerialiser extends JsonSerializer<Record> { private static final ObjectMapper DEFAULT_MAPPER = mapperWith(); public static ObjectMapper mapperWith(JsonSerializer<?>...extraSerialisers) { ObjectMapper mapper = new ObjectMapper(); SimpleModule simpleModule = new SimpleModule("SimpleModule", Version.unknownVersion()); simpleModule.addSerializer(new ReflectiveRecordSerialiser()); simpleModule.addSerializer(new StreamSerialiser()); Stream.of(extraSerialisers).forEach(simpleModule::addSerializer); mapper.registerModules(simpleModule); return mapper; } private static final class StreamSerialiser extends JsonSerializer<Stream> { private static final class WrappedIOException extends RuntimeException { private final IOException e; private WrappedIOException(IOException e) { this.e = e; } public IOException getWrappedException() { return e; } } @Override public Class<Stream> handledType() { return Stream.class; } @Override public void serialize(Stream stream, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException { jsonGenerator.writeStartArray(); try { stream.forEach(item -> { try { serializerProvider.defaultSerializeValue(item, jsonGenerator); } catch (IOException e) { throw new WrappedIOException(e); } }); } catch (WrappedIOException e) { throw e.getWrappedException(); } jsonGenerator.writeEndArray(); } } public static String toJson(Value...values) throws JsonProcessingException { return toJson($$(values)); } public static String toJson(Record record) throws JsonProcessingException { return DEFAULT_MAPPER.writeValueAsString(record); } public static String toJson(Record...records) throws JsonProcessingException { return toJson(Stream.of(records)); } public static String toJson(Record record, JsonSerializer<?>...extraSerialisers) throws JsonProcessingException { return mapperWith(extraSerialisers).writeValueAsString(record); } public static String toJson(Collection<Record> records) throws JsonProcessingException { return toJson(records.stream()); } public static String toJson(Stream<Record> records) throws JsonProcessingException { return DEFAULT_MAPPER.writeValueAsString(records); } public static String toJson(Collection<Record> records, JsonSerializer<?>...extraSerialisers) throws JsonProcessingException { return mapperWith(extraSerialisers).writeValueAsString(records); } public static String toJson(Stream<Record> records, JsonSerializer<?>...extraSerialisers) throws JsonProcessingException { return mapperWith(extraSerialisers).writeValueAsString(records); } public static String toJson(Map<String, Record> records) throws JsonProcessingException { return DEFAULT_MAPPER.writeValueAsString(records); } public static String toJson(Map<String, Record> records, JsonSerializer<?>...extraSerialisers) throws JsonProcessingException { return mapperWith(extraSerialisers).writeValueAsString(records); } @Override public Class<Record> handledType() { return Record.class; } @Override public void serialize(Record o, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException { jsonGenerator.writeStartObject(); for (Map.Entry<Key<?>, Object> entry : o.values().entrySet()) { jsonGenerator.writeFieldName(entry.getKey().name()); serializerProvider.defaultSerializeValue(entry.getValue(), jsonGenerator); } jsonGenerator.writeEndObject(); } }