2015-05-03 2 views
0

Я использую GSON для анализа данных JSON в Java, и я сталкиваюсь с ошибкой, указанной в заголовке. Я работаю с API, который возвращает следующий JSON данные:Gson как избежать Ожидаемый BEGIN_ARRAY, но был BEGIN_OBJECT?

{ 
    "STATUS": "SUCCESS", 
    "NUM_RECORDS": "5", 
    "MESSAGE": "5 records found", 
    "AVAILABILITY_UPDATED_TIMESTAMP": "2015-05-03T13:59:08.541-07:00", 
    "AVAILABILITY_REQUEST_TIMESTAMP": "2015-05-03T13:59:08.490-07:00", 
    "AVL": [ 
    { 
     "TYPE": "ON", 
     "BFID": "205052", 
     "NAME": "5th St (500-598)", 
     "RATES": { 
     "RS": [ 
      { 
      "BEG": "12:00 AM", 
      "END": "12:00 PM", 
      "RATE": "0", 
      "RQ": "No charge" 
      }, 
      { 
      "BEG": "12:00 PM", 
      "END": "6:00 PM", 
      "RATE": "5", 
      "RQ": "Per hour" 
      }, 
      { 
      "BEG": "6:00 PM", 
      "END": "12:00 AM", 
      "RATE": "0", 
      "RQ": "No charge" 
      } 
     ] 
     }, 
     "PTS": "2", 
     "LOC": "-122.4002212834,37.7776161738,-122.3989619795,37.7766113458" 
    }, 
    { 
     "TYPE": "ON", 
     "BFID": "205042", 
     "NAME": "5th St (450-498)", 
     "RATES": { 
     "RS": { 
      "BEG": "12:00 AM", 
      "END": "12:00 AM", 
      "RATE": "0", 
      "RQ": "No charge" 
     } 
     }, 
     "PTS": "2", 
     "LOC": "-122.4015027158,37.7786330718,-122.4005149869,37.7778485214" 
    }, 
    ] 
} 

я могу видеть, где проблема возникает, то RS поле может содержать либо массив объектов (назовем этот объект RInfo) или в некоторых случаях будет содержать только один из этого объекта RInfo, который не содержится в массиве. Я думаю, что ошибка возникает из-за того, что GSON ищет массив, но обнаружил объект. Я не могу изменить структуру файла JSON, потому что он был предоставлен API.

Я могу разобрать информацию успешно, пока RS является массивом RInfo объектов, но в некоторых случаях RS содержит только один RInfo объект так, эта ошибка возникает.

Есть ли способ справиться с этим в GSON?

* Обновление

Я попробовал решение, которое было связано ранее. Вот то, что я от этого решения:

class RSDeserializer implements JsonDeserializer<RateInfo[]> { 

    @Override 
    public RateInfo[] deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) 
      throws JsonParseException 
    { 


     if (json instanceof JsonArray) { 
      System.out.println("fromJson in RSD:" + new Gson().fromJson(json, RateInfo[].class)); 
      return new Gson().fromJson(json, RateInfo[].class); 
     } 
     RateInfo rI = context.deserialize(json, RateInfo.class); 

     return new RateInfo[] { rI }; 
    } 

} 

Я также создал новый GsonBuilder следующим

GsonBuilder gsonBuilder = new GsonBuilder(); 
    gsonBuilder.registerTypeAdapter(RateInfo[].class, new RSDeserializer()); 
    Gson gson = gsonBuilder.create(); 

Это не похоже на заказ десериализатор постоянно используется, потому что оператор печати никогда не было распечатывается в консоли. После этого я попытался обезвредить json, используя MyOBJ info = gson.fromJson(json, MyOBJ.class);, эта строка дает мне ожидаемое BEGIN_ARRAY, но это исключение BEGIN_OBJECT.

+0

Я пробовал это решение, но не смог заставить его работать. Производит ли десериализация на более сложных Json-файлах, например, с той, с которой я работаю? –

+0

Да, отлично работает с более сложными JSON. Любая ошибка с вашим пользовательским решением? –

+0

Я обновил свой первоначальный пост тем, что я пробовал. Кажется, что пользовательский десериализатор не используется. –

ответ

0

Вы должны обновить десериализатор сказать, что вы хотите вернуть List<RateInfo>:

class RSDeserializer implements JsonDeserializer<List<RateInfo>> { 
    @Override 
    public List<RateInfo> deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { 
     if (json instanceof JsonArray) { 
      return Arrays.asList(context.deserialize(json, RateInfo[].class)); 
     } 
     return Collections.singletonList(context.deserialize(json, RateInfo.class)); 
    } 
} 

, и вы должны также сказать анализатору, что это тип десериализации тоже при регистрации этого адаптера :

Type t = new TypeToken<List<RateInfo>>(){}.getType(); 
Gson gson = new GsonBuilder().registerTypeAdapter(t, new RSDeserializer()).create(); 

полный рабочий пример можно найти в моем gist.

Смежные вопросы