All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.activej.json.SubclassJsonCodec Maven / Gradle / Ivy

The newest version!
package io.activej.json;

import com.dslplatform.json.JsonReader;
import com.dslplatform.json.JsonWriter;
import io.activej.common.builder.AbstractBuilder;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

import static com.dslplatform.json.JsonWriter.*;

public final class SubclassJsonCodec implements JsonCodec {
	private final Map> tagToCodec = new HashMap<>();
	private final Map, String> classToTag = new HashMap<>();

	private SubclassJsonCodec() {
	}

	public static  SubclassJsonCodec.Builder builder() {
		return new SubclassJsonCodec().new Builder();
	}

	public final class Builder extends AbstractBuilder> {
		private Builder() {}

		public  Builder with(Class type, JsonCodec codec) {
			return with(type, type.getSimpleName(), codec);
		}

		public  Builder with(Class type, String name, JsonCodec codec) {
			tagToCodec.put(name, codec);
			classToTag.put(type, name);
			if (codec instanceof SubclassJsonCodec) {
				tagToCodec.putAll(((SubclassJsonCodec) codec).tagToCodec);
				classToTag.putAll(((SubclassJsonCodec) codec).classToTag);
			}
			return this;
		}

		@Override
		protected SubclassJsonCodec doBuild() {
			return SubclassJsonCodec.this;
		}
	}

	@Override
	public void write(JsonWriter writer, T value) {
		writer.writeByte(OBJECT_START);
		String tag = classToTag.get(value.getClass());
		writer.writeString(tag);
		writer.writeByte(SEMI);

		//noinspection unchecked
		JsonCodec codec = (JsonCodec) tagToCodec.get(tag);

		codec.write(writer, value);

		writer.writeByte(OBJECT_END);
	}

	@Override
	public T read(JsonReader reader) throws IOException {
		if (reader.last() != OBJECT_START) throw reader.newParseError("Expected '{'");
		reader.getNextToken();
		String key = reader.readKey();
		JsonCodec codec = tagToCodec.get(key);
		if (codec == null) throw reader.newParseError("Unexpected key: '" + key + "'");
		T result = codec.read(reader);
		if (reader.getNextToken() != OBJECT_END) throw reader.newParseError("Expected '}'");
		return result;
	}
}