bluelinelabs / LoganSquare

Screaming fast JSON parsing and serialization library for Android.
Apache License 2.0
3.21k stars 306 forks source link

How to parse JsonArray or JsonObject with no field name. #142

Closed fromdestiny closed 8 years ago

fromdestiny commented 8 years ago

I'm using retrofit2 and trying to change converterfactory from Gson to Logansquare. Everything was fine before I met things that I write blow.

I would like parse such as

  1. JsonArray with no filed name ["1" , "2" , "3"]
  2. Map<K,V> ["xx" : { } , "xx2" : { }]

Is there any way to parse them ?

Anyone can help me?

ndmt commented 8 years ago

Hi, I'm new in LoganSquare and I have the same problem here: For example my json look like this (location values) : [48.84, 3.55]

I tried to implements a converter like this (code in comments doesn't work)

public class GeometryConverter implements TypeConverter<LatLng> {

    static final TypeReference<List<Double>> TYPE_REFERENCE = new TypeReference<List<Double>>() {};
    static final ParameterizedType<List<Double>> PARAMETERIZED_TYPE = new ParameterizedType<List<Double>>() {};

    static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();

    @Override
    public LatLng parse(JsonParser jsonParser) throws IOException {
        try {
//            List<Double> location = jsonParser.readValueAs(TYPE_REFERENCE);
//            List<Double> location = LoganSquare.mapperFor(PARAMETERIZED_TYPE).parse(jsonParser);
            List<Object> objects = OBJECT_MAPPER.parseList(jsonParser);
            return new LatLng((double) objects.get(1), (double) objects.get(0));
        } catch (Exception exp) {
            Timber.w(exp, "failed to parse LatLng");
            return null;
        }
    }

    @Override
    public void serialize(LatLng latLng, String fieldName, boolean writeFieldNameForObject, JsonGenerator jsonGenerator) throws IOException {

    }

}

It works with OBJECT_MAPPER.parseList(jsonParser); but I don't really like how new LatLng((double) objects.get(1), (double) objects.get(0)); looks

Do you have any suggestions or tips ?

EricKuck commented 8 years ago

@fromdestiny

List<String> list = LoganSquare.parseList(inputStream, String.class);

for your first one. For your second one follow any of the examples in this project. It's just a POJO. Nothing special at all.

EricKuck commented 8 years ago

@ndmt It seems like this should work for you:

List<Float> list = LoganSquare.parseList(json, Float.class);

ndmt commented 8 years ago

@EricKuck How do I transform my JsonParser into String ? I tried : List<Float> objects = LoganSquare.parseList(jsonParser.readValueAs(String.class), Float.class); but it's not working List<Float> objects = LoganSquare.parseList(jsonParser.getValueAsString(), Float.class); same, not working :/

EricKuck commented 8 years ago

I don't understand your question. Are you looking for a List<String> instead of a List<Float>? Why are you trying to use the jsonParser at all?

ndmt commented 8 years ago

Because it's the implementation of TypeConverter (I use Retrofit)

EricKuck commented 8 years ago

Can you post a more detailed example? I see you're using ObjectMapper in your converter as well, which is very confusing. It seems like the code I originally responded to you with would work fine.

ndmt commented 8 years ago

Here is the json response :

{ 
...
    "geoloc":[
        48.864543,
        2.340997
    ]
...
}

Here is my attribute of my object:

    @JsonField(name = "geoloc")
    LatLng location;

I put this on Retrofit :

    @Provides
    @Singleton
    Retrofit providesRetrofit(OkHttpClient okHttpClient) {
        LoganSquare.registerTypeConverter(LatLng.class, new LatLngConverter());
        return new Retrofit.Builder()
                .baseUrl(ENDPOINT)
                .addConverterFactory(LoganSquareConverterFactory.create())
                .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
                .client(okHttpClient)
                .build();
    }

here is my converter (empty)

    public class LatLngConverter implements TypeConverter<LatLng> {

    @Override
    public LatLng parse(JsonParser jsonParser) throws IOException {
        try {

            // and now ?
            return new LatLng();
        } catch (Exception exp) {
            Timber.e(exp, "failed to parse LatLng");
            return null;
        }
    }

    @Override
    public void serialize(LatLng latLng, String fieldName, boolean writeFieldNameForObject, JsonGenerator jsonGenerator) throws IOException {

    }
}

So, my question is, how can I parse my List into LatLng object automatically ?

EricKuck commented 8 years ago

You can't get it to a LatLng directly, unfortunately. You'd have to parse it to an Integer list, then create a LatLng based on that.

ndmt commented 8 years ago

Ok I found a way:

public class LatLngConverter implements TypeConverter<LatLng> {

    @Override
    public LatLng parse(JsonParser jsonParser) throws IOException {
        try {
            List<Float> list = LoganSquare.mapperFor(Float.class).parseList(jsonParser);
            return new LatLng(list.get(0), list.get(1));
        } catch (Exception exp) {
            Timber.e(exp, "failed to parse LatLng");
            return null;
        }
    }

    @Override
    public void serialize(LatLng latLng, String fieldName, boolean writeFieldNameForObject, JsonGenerator jsonGenerator) throws IOException {

    }
}

At first I had some problems because I tried to parse a Double but It's not yet supported

mannodermaus commented 8 years ago

In case you want to support serialization as well, you should be able to use this:

@Override 
public void serialize(LatLng latLng, String fieldName, boolean writeFieldNameForObject, JsonGenerator jsonGenerator) throws IOException {
    jsonGenerator.writeStartArray();
    jsonGenerator.writeNumber(latLng.getLatitude());
    jsonGenerator.writeNumber(latLng.getLongitude());
    jsonGenerator.writeEndArray();
} 
ndmt commented 8 years ago

Thank you for your help :)

fromdestiny commented 8 years ago

@EricKuck Thank you for replying. It works.

renannprado commented 7 years ago

@EricKuck how can I make the LoganSquare.parseList work with an annotated class given that the root element of the json to be deserialized is the array with no name?

safeer-ahmed commented 5 years ago

What about this JSON?

[
    [
        1,
        "Type 1"
    ],
    [
        2,
        "Type 2"
    ],
    [
        3,
        "Type 3"
    ] 
]

What will be POJO of it? Tried to find on jsonschema2pojo but that's not returning anything.