Open vipulpurohit opened 11 years ago
That would make the API fairly wonky... two versions of every JSON call.
how about using a Converter object just like Retrofit does? this will remove a dependency on Gson
Hm, doing this would be a breaking API change. Let me see how I can go about this gracefully.
Check out hte following, that allows you to use a custom parser:
public <T> ResponseFuture<T> as(AsyncParser<T> parser);
Did anyone actually implement a Jackson AsyncParser for Ion?
I can provide a sample in the README or something.
That would be nice. We use Jackson in our tool and the conversion is a bit lame (from Gson to String to Jackson JSON).
Hey @koush, I just had a look at your GsonParser and gave it a try. Actually I do realized that I do not need an object back but an instance of the JsonParser that I can pass to different methods to do the actual stream parsing. So I came up with that JacksonParser class:
public class JacksonParser implements AsyncParser<JsonParser> {
public JacksonParser() {
}
@Override
public Future<JsonParser> parse(DataEmitter emitter) {
return new ByteBufferListParser().parse(emitter)
.then(new TransformFuture<JsonParser, ByteBufferList>() {
@Override
protected void transform(ByteBufferList result) throws Exception {
JsonFactory jsonFactory = new JsonFactory();
JsonParser jsonParser = jsonFactory
.createJsonParser(new InputStreamReader(new ByteBufferListInputStream(result)));
setComplete(null, jsonParser);
}
});
}
@Override
public void write(DataSink sink, JsonParser value, CompletedCallback completed) {
new StringParser().write(sink, "", completed);
}
}
Now I get a "loaded" Jackson json parser back and can actually do the transformation to the object. I could also create more specific parsers, that would simply give me the target object back. Maybe in a next iteration ;)
However, I do not really get the purpose of the write method. The implementation above makes no sense, as it does not use the value object at all. Maybe you can provide some more infos on that?
Anyway, thanks a lot for this awesome lib :+1:
And as a follow up, a more generic and GsonParser like approach would be this class:
public class JacksonParser<T extends JsonNode> implements AsyncParser<T> {
public JacksonParser() {
}
@Override
public Future<T> parse(DataEmitter emitter) {
return new ByteBufferListParser().parse(emitter)
.then(new TransformFuture<T, ByteBufferList>() {
@Override
protected void transform(ByteBufferList result) throws Exception {
ObjectMapper mapper = new ObjectMapper();
T node = (T) mapper.readTree(new InputStreamReader(new ByteBufferListInputStream(result)));
setComplete(null, node);
}
});
}
@Override
public void write(DataSink sink, T value, CompletedCallback completed) {
ObjectMapper mapper = new ObjectMapper();
try {
new StringParser().write(sink, mapper.writeValueAsString(value), completed);
} catch (IOException e) {
e.printStackTrace();
}
}
}
You can call it with the type that you want (ArrayNode, ObjectNode, etc.)
ObjectNode node = Ion.with(context, "http://www.someurl.com/json/").as(new JacksonParser<ObjectNode>()).get();
I am still not very sure about the write method though :)
The second example looks correct, write method included.
@koush ah cool! So the write method is like the "reverse" to the parse method? This makes in the second example. With the first it does not really make sense, as what would be the "reverse" to a stream parser!?
Anyhow, I need the stream parser as I need to save memory on big JSON files. Reading the whole into memory like with the GsonParser or the second example does not work for me.
Feel free to share the code somewhere in your comments ;) Then I guess this issue can be closed again!
The problem is that streams are blocking constructs. Which is not so good in a async context. It would mean that Ion would need to fire up a background thread.
How big is your JSON Payload (in bytes) that you need a stream to parse it?
Anything under 500k should be fine on most devices.
For the write method, it is probably better to write to a bytearrayoutputstream, and then pass that to the sink.
@koush the JSON data is up to 2 MB. I use stream parsing to directly dump data into the database for later access. But for me it's fine if I just receive the "configured" stream parser back, so the first example does the trick.
I checked the classes and I do not see how I would pass a bytearrayoutputstream to the sink.
@deradam Thanks for jackson parser
but how i can use it with any model class i have like what we can do with Gson "new TypeToken
Can you please add Jackson JSON parser in ION like you did for GSON, its because Jackson is much faster then GSON.
Thanks