2016-12-07 4 views
0

У меня есть JSON ниже:Пользовательские десериализации в карты с помощью Gson

{ 
    "abc": { 
     "linkedTo": "count", 
     // possibly more data... 
    }, 
    "plmtq": { 
     "linkedTo": "title", 
     "decode": "true", 
     // possibly more data... 
    } 
} 

нужно загрузить этот JSON в Map<String, Holder>, с ключами "abc" и "plmtq".
Ниже мой Holder класс:

public class Holder { 
    private final Map<String, String> data; 

    public Holder(Map<String, String> data) { 
    this.data = data; 
    } 

    // More methods in this class... 
} 

JSON не соответствует моей классовой структуры, но я не могу изменить JSON или классы.
Что мне нужно - это способ настройки десериализации, поэтому я могу разобрать JSON в Map<String, Holder>.
Есть ли способ сделать это?


Ниже приведен код, который делает это, но это выглядит слишком сложным и должен быть более простой способ сделать это ...

private static Map<String, Holder> getMap(String jsonLine) 
{ 
    Map<String, Holder> holder = new HashMap<>(); 
    JsonElement jelement = new JsonParser().parse(jsonLine); 
    JsonObject jobject = jelement.getAsJsonObject(); 

    for (Map.Entry<String, JsonElement> entry : jobject.entrySet()) 
    { 
     Map<String, String> metadata = new HashMap<>(); 
     JsonObject element = entry.getValue().getAsJsonObject(); 

     for (Map.Entry<String, JsonElement> entry2 : element.entrySet()) 
     { 
      metadata.put(entry2.getKey(), entry2.getValue().getAsString()); 
     } 

     holder.put(entry.getKey(), new Holder(metadata)); 
    } 
    return holder; 
} 
+0

Этот JSON не соответствует вашей иерархии объектов 'Holder'. –

+0

@SotiriosDelimanolis Он подходит? 'holder'' (Карта holder = new HashMap <>();)' map будет иметь ключ как 'abc', и его значение будет' Holder', в котором ключ карты данных имеет 'linkedTo' и значение это 'count'. Аналогично для 'plmtq'. – john

+0

Извините, ваш метод разбора запутан. Это может быть выполнимо в одной строке с Джексоном. У Gson нет такого синтаксического анализа многих функций. –

ответ

1

Если вы действительно нужно держать Holder класс как есть, единственный вариант, о котором я могу думать, - создать собственный десериализатор для вашего класса Holder.

Выполняя это, всякий раз, когда вы говорите Gson для разбора некоторого JSON в объекте Holder, он будет использовать ваш десериализатор вместо того, чтобы делать это «обычным способом» (т. Е. Сопоставление ключей JSON с объектными свойствами).

Что-то вроде этого:

private class HolderDeserializer implements JsonDeserializer<Holder> { 

    @Override 
    public Holder deserialize(JsonElement json, Type type, JsonDeserializationContext context) 
    throws JsonParseException { 

    Type mapType = new TypeToken<Map<String, String>>() {}.getType(); 
    Map<String, String> data = context.deserialize(json, mapType); 

    return new Holder(data); 
    } 
} 

Тогда вы регистрируете свой десериализатор при создании Gson объекта:

GsonBuilder gsonBuilder = new GsonBuilder(); 
gsonBuilder.registerTypeAdapter(Holder.class, new HolderDeserializer()); 
Gson gson = gsonBuilder.create(); 

И, наконец, вы разобрать ваш JSON как это:

Type responseType = new TypeToken<Map<String, Holder>>() {}.getType(); 
Map<String, Holder> response = gson.fromJson(jsonLine, responseType); 

Вы можете посмотреть документы Gson для пользовательских (de)serialization и this other answer, чтобы получить дополнительную информацию ...

Примечание: этот ответ редактировался, чтобы уточнить его после обсуждения в комментариях/чате.

+0

Я имею в виду, что я делаю много других вещей в «Держателе», и это необходимо в основном. Также у меня не может быть pojo для класса Holder bcoz. У меня может быть много полей в этом классе, и этот json приходит из базы данных каждые 15 минут. Помните, что это лучший способ сделать это? – john

+0

@ david и имеющие эти 2 атрибута 'linkedTo' и' decode' в вашем классе 'Holder' вместе со всем остальным, что у вас там, не работает? – MikO

+0

Я имею в виду наличие этих полей в поле 'data'.Обратите внимание, что согласно вашему JSON, класс 'Holder' не содержит _not_, содержит' Map' под названием 'data' ... в вашем JSON нет поля данных. – MikO