Я пытаюсь преобразовать JSON в объект java в Android, но, похоже, это не работает.

Gson gson = new Gson();
Person person = gson.fromJson(s, Person.class);
Toast toast = Toast.makeText(getApplicationContext(), "Welcome back " + person.getDisplayName(), duration);
toast.show();

Где Person.class

com.google.api.services.plus.model.Person

Я получаю такие ошибки преобразования типа:

wrong object type: Ljava/lang/Double; Ljava/lang/Integer;
java.lang.IllegalArgumentException: invalid value for field

Но я хочу повторно использовать этот объект модели из библиотеки API, так что как это исправить?

РЕДАКТИРОВАТЬ:

Чтобы доказать эту проблему в более простой форме, обратитесь к этому примеру.

com.google.api.services.plus.model.Person;

Gson g = new Gson();

    Person p1 = new Person();
    p1.setDisplayName("Test");
    p1.setCircledByCount(10);

    String json = g.toJson(p1);
    Person fromJson = g.fromJson(json, Person.class);
    System.out.println(fromJson.getDisplayName());

Выдает то же исключение.

Exception in thread "main" java.lang.IllegalArgumentException: Can not set java.lang.Integer field com.google.api.services.plus.model.Person.circledByCount to java.lang.Double
at sun.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(Unknown Source)
at sun.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(Unknown Source)

Я делаю что-то неправильно? благодаря

1
user1089599 23 Фев 2014 в 18:54
1
Опубликуйте свой класс модели и json
 – 
Pararth
23 Фев 2014 в 18:55
1
Честно говоря, вы не должны использовать GSON с этим классом. Он не предназначен для использования с GSON. У него есть собственная встроенная логика для сериализации в JSON, а библиотека, в которую он входит, выполняет десериализацию для него.
 – 
Brian Roach
24 Фев 2014 в 10:33

3 ответа

Лучший ответ

Проблема в том, что используемый вами класс не предназначен / не предназначен для использования с Gson.

Основная проблема заключается в том, что Person расширяет GenericJson, который расширяет GenericData, который расширяет AbstractMap<String, Object> ... и это является проблемой.

Когда Gson пытается десериализовать JSON, он использует его MapTypeAdapterFactory, что, к сожалению, приводит к тому, что числовой тип JSON для "circledByCount" читается в Java как Double.

Затем проявляется сложность этого класса Person. Если вы посмотрите на исходный код, он фактически использует аннотации и переопределенные методы put для заполнения поля в Person. Если вы посмотрите на трассировку стека, вы действительно увидите, что происходит:

Exception in thread "main" java.lang.IllegalArgumentException: Can not set java.lang.Integer field com.google.api.services.plus.model.Person.circledByCount to java.lang.Double
    at sun.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(UnsafeFieldAccessorImpl.java:164)
    at sun.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(UnsafeFieldAccessorImpl.java:168)
    at sun.reflect.UnsafeObjectFieldAccessorImpl.set(UnsafeObjectFieldAccessorImpl.java:81)
    at java.lang.reflect.Field.set(Field.java:680)
    at com.google.api.client.util.FieldInfo.setFieldValue(FieldInfo.java:245)
    at com.google.api.client.util.FieldInfo.setValue(FieldInfo.java:206)
    at com.google.api.client.util.GenericData.put(GenericData.java:103)
    at com.google.api.client.util.GenericData.put(GenericData.java:47)
    at com.google.gson.internal.bind.MapTypeAdapterFactory$Adapter.read(MapTypeAdapterFactory.java:188)
    at com.google.gson.internal.bind.MapTypeAdapterFactory$Adapter.read(MapTypeAdapterFactory.java:145)
    at com.google.gson.Gson.fromJson(Gson.java:803)
    at com.google.gson.Gson.fromJson(Gson.java:768)
    at com.google.gson.Gson.fromJson(Gson.java:717)
    at com.google.gson.Gson.fromJson(Gson.java:689)

Gson вызывает метод GenericData put() (потому что он знает, что это Map). Этот метод фактически заполняет аннотированное поле circledByCount посредством отражения. И ... это не тот тип.

Итак, в основном ... это не сработает с Gson. По крайней мере, без написания пользовательского JsonDeserializer, но глядя на класс, это будет довольно сложно.

6
Brian Roach 24 Фев 2014 в 11:16
Спасибо за подробное объяснение. Кажется странным иметь классы моделей и использовать сериализатор json, отличный от GSON, когда он используется во многих других местах клиентских библиотек. Однако я уверен, что для этого есть веская причина!
 – 
user1089599
24 Фев 2014 в 17:48

Ваш личный класс должен иметь те же поля и имя, что и анализируемый вами JSON.

0
AlexanderNajafi 23 Фев 2014 в 19:04

Ваш JSON String имеет значение Double, а объект Person, который вы хотите преобразовать, имеет значение Integer.

Пожалуйста, проверьте объект Person с обеих сторон. Лучше скопировать и вставить тот же объект Person на стороне приложения Android ..

0
naXa stands with Ukraine 15 Апр 2014 в 03:09
Это тот же класс модели из API Google, который указан в сообщении. JSON создается контроллером Spring mvc, возвращающим объект person. Может ли сериализатор Jackson на стороне сервера вызывать проблему?
 – 
user1089599
23 Фев 2014 в 19:14
Если строка JSON возвращается с сервера, это не может быть проблемой сериализатора Джексона. Дважды проверьте свой личный класс. Если вы можете предоставить строку JSON и класс Person как на стороне сервера, так и на стороне клиента ..
 – 
Charitha
24 Фев 2014 в 08:39