JSON String към Java обект с помощта на GSON

Опитвам се да анализирам json в java.

Имам следния низ, който е валиден json според jsonlint.com

private final static String LOC_JSON = 
         "["
        +"{"
        +"  \"lat1\": 39.737567,"
        +"  \"lat2\": 32.7801399,"
        +"  \"long1\": -104.98471790000002,"
        +"  \"long2\": -96.80045109999998"
        +"},"
        +"  ["
        +"      {"
        +"          \"lat\": {"
        +"              \"b\": 38.88368709500021,"
        +"              \"d\": 40.620468491667026"
        +"          },"
        +"          \"long\": {"
        +"          \"b\": -105.75306170749764,"
        +"          \"d\": -104.675854661387"
        +"          }"
        +"      }"
        +"  ]"
        +"]";

Опитвам се да го анализирам в обект и получавам следната грешка. „Очаква се BEGIN_OBJECT, но беше BEGIN_ARRAY на ред 1, колона 2“

            Gson gson = new Gson();
        BoxSearch b = gson.fromJson( LOC_JSON, BoxSearch.class ); 

BoxSearch се състои от това.

private Number lat1;
private Number lat2;
private Number long1;
private Number long2;
private Boxes[] boxes;

Boxes е обект Latitude и обект Longitude, които са дефинирани еднакви.

private String b;
private String d;

Мога да анализирам атрибутите от по-високо ниво (lat1,lat2,long1 и long2) в по-прост BoxSearch обект, който има само тези 4 атрибута. Проблемът идва, когато json и обектът са по-сложни. Възможно ли е изобщо да направя това, което се опитвам?

Надявам се, че съм предоставил достатъчно информация, за да получа малко помощ. Ще се радвам да предоставя повече информация или дори тестов проект, ако е необходимо. Изпълнявам това като junit тест.

Благодаря.


person user2415153    schedule 23.05.2013    source източник
comment
възможен дубликат на GSON хвърляне Очакваше се BEGIN_OBJECT, но беше BEGIN_ARRAY? - вашият JSON е масив, а не обект. Ще имате проблем обаче, защото това е масив, съдържащ различни типове обекти (обект и масив), с които не можете да се справите, без да напишете персонализиран десериализатор   -  person Brian Roach    schedule 24.05.2013
comment
@BrianRoach това е по-скоро отговор ;)   -  person    schedule 24.05.2013
comment
@RC. Да... Хм. Мисля, че може би ще го преместя, старото Q отговаря защо получава грешката, но решението на неговия случай е различно   -  person Brian Roach    schedule 24.05.2013
comment
Преминах през възможния дубликат, но този обект е прост, а не сложен. Има ли по-добър начин за организиране на json низа? Моят потребителски интерфейс го сглобява (на базата на google maps), но мога да го манипулирам. Предполагам, че ще опитам по-прост/плосък обект. Или писането на персонализиран десериализатор е правилният начин?   -  person user2415153    schedule 24.05.2013
comment
@user2415153 - вижте моя разширен отговор по-долу. Ако вие сте този, който генерира JSON, тогава да - преработването му така, че да е обект, а не масив, ще направи живота ви много по-лесен. Позволете ми да разширя това малко в моя отговор; редактиране.   -  person Brian Roach    schedule 24.05.2013
comment
@user2415153 вижте окончателното редактиране на моя отговор.   -  person Brian Roach    schedule 24.05.2013


Отговори (2)


Причината за грешката е, че вашият JSON на най-високо ниво е масив, а не обект. Това се покрива от GSON, изхвърлящ „Очаква се BEGIN_OBJECT, но беше BEGIN_ARRAY“?.

Решението там обаче няма да работи за вашия JSON, защото имате масив от смесени типове (обект и масив), а не масив от един тип обект. За целта ще трябва да напишете персонализиран десериализатор (вижте Разделът от ръководството на потребителя на Gson, който обхваща това) или използвайте JsonParser клас директно и извлича данните от дървото за анализ.

Редактиране от коментарите по-горе:

Ако вие сте този, който създава JSON, изглежда, че това, което искате, е масив от BoxSearch обекта?

Въз основа на вашия Java BoxSearch клас ще ви трябва JSON, структуриран като:

[
    {
        "lat1" : 39.737567,
        "lat2" : 32.7801399,
        "long1" : -104.98471790000002,
        "long2" : -96.80045109999998,
        "boxes" : [ 
                    {
                      "lat": {
                          "b": 38.88368709500021,
                          "d": 40.620468491667026
                      },
                      "long": {
                          "b": -105.75306170749764,
                          "d": -104.675854661387
                      }
                    }
                  ]
    }
]

Обаче начинът, по който сте дефинирали класа Boxes, няма да работи за това. (Имате предвид да имате масив от тях?). Както е, трябва да изглежда така:

class Boxes {
    Box lat;
    @SerializedName("long")
    Box lon;
}

class Box {
   String b;
   String d;
}

Сега имате масив, съдържащ един тип обект (BoxSearch), който можете да десериализирате с:

Type collectionType = new TypeToken<Collection<BoxSearch>>(){}.getType();
Collection<BoxSearch> boxSearchCollection = gson.fromJson(json, collectionType);

Ако наистина не се нуждаете от масив от тях, отървете се от външния масив и просто направете:

gson.fromJson(json, BoxSearch.class);
person Brian Roach    schedule 23.05.2013
comment
Благодаря ти много Брайън, тази лека корекция на json и всичко е наред. Бих гласувал за този отговор, но нямам доверие на улицата. Кодът работи като шампион. В случай, че хората копират и поставят този отговор, Box long; трябва да се преименува :-) - person user2415153; 24.05.2013
comment
О, да, имах нужда от масива. Благодаря отново. - person user2415153; 24.05.2013
comment
@user2415153 Промених кода, така че да работи с "long" в JSON - вижте отговора сега :) Не забелязах това, съжалявам. Що се отнася до гласуването за - можете да приемете отговора ми ;) и се радвам, че можах да помогна! - person Brian Roach; 24.05.2013
comment
Изискано решение! Току-що преименувах променливите на пълните думи. Приема се като отговор! Благодаря отново! - person user2415153; 24.05.2013

Gson gson = new Gson();
gson.fromJson(jsonStr,YourClass.class);

много лесно.

person 王怡飞    schedule 18.12.2015
comment
това ми помага да конвертирам json обект, който има списък вътре. Преобразувам json низа в Object.class - person Ashkan; 12.01.2017