package com.koushikdutta.ion.gson; import com.google.gson.JsonElement; import com.google.gson.JsonParseException; import com.google.gson.JsonParser; import com.google.gson.stream.JsonReader; import com.koushikdutta.async.ByteBufferList; import com.koushikdutta.async.DataEmitter; import com.koushikdutta.async.DataSink; import com.koushikdutta.async.callback.CompletedCallback; import com.koushikdutta.async.future.Future; import com.koushikdutta.async.future.TransformFuture; import com.koushikdutta.async.parser.AsyncParser; import com.koushikdutta.async.parser.ByteBufferListParser; import com.koushikdutta.async.parser.StringParser; import com.koushikdutta.async.stream.ByteBufferListInputStream; import java.io.InputStreamReader; import java.lang.reflect.Type; import java.nio.charset.Charset; /** * Created by koush on 5/27/13. */ public abstract class GsonParser<T extends JsonElement> implements AsyncParser<T> { Charset forcedCharset; Class<? extends JsonElement> clazz; public GsonParser(Class<? extends T> clazz) { this.clazz = clazz; } public GsonParser(Class<? extends T> clazz, Charset charset) { this(clazz); this.forcedCharset = charset; } @Override public Future<T> parse(DataEmitter emitter) { final String charset = emitter.charset(); return new ByteBufferListParser().parse(emitter) .then(new TransformFuture<T, ByteBufferList>() { @Override protected void transform(ByteBufferList result) throws Exception { JsonParser parser = new JsonParser(); ByteBufferListInputStream bis = new ByteBufferListInputStream(result); InputStreamReader isr; if (forcedCharset != null) isr = new InputStreamReader(bis, forcedCharset); else if (charset != null) isr = new InputStreamReader(bis, charset); else isr = new InputStreamReader(bis); JsonElement parsed = parser.parse(new JsonReader(isr)); if (parsed.isJsonNull() || parsed.isJsonPrimitive()) throw new JsonParseException("unable to parse json"); if (!clazz.isInstance(parsed)) throw new ClassCastException(parsed.getClass().getCanonicalName() + " can not be casted to " + clazz.getCanonicalName()); setComplete(null, (T)parsed); } }); } @Override public void write(DataSink sink, T value, CompletedCallback completed) { new StringParser().write(sink, value.toString(), completed); } @Override public Type getType() { return clazz; } }