Разбор нескольких типов в массиве JSON с помощью gson

Я пытаюсь разобрать строку JSON с помощью POJO с gson, но столкнулся с проблемой при попытке прочитать следующий массив JSON:

{"translate":"chat.type.text","with":[{"insertion":"woder22","clickEvent":{"action":"suggest_command","value":"/msg woder22 "},"hoverEvent":{"action":"show_entity","value":"{name:\"woder22\",id:\"bbd02ce0-24de-4683-8c8f-5d7e6b7dffa6\",}"},"text":"woder22"},"hi"]}

Все работает нормально, пока я не доберусь до части «с», я пытаюсь разобрать ее, используя следующие POJO.

public class ChatMessage {
    private String text = "";
    private String translate;
    private List<With> with = new ArrayList<With>();
    private String score;
    private String selector;
    private List<Node> extra;
    private String bold = "false";
    private String italic = "false";
    private String underlined = "false";
    private String strikethrough = "false";
    private String obfuscated = "false";
    private String color;
    private Clicked clickEvent;
    private Hover hoverEvent;
    private String insertion;

    //getter and setter method here

}

class Node {
    private String color;
    private String text;

    public String getColor() {
        return color;
    }
    public void setColor(String color) {
        this.color = color;
    }
    public String getText() {
        return text;
    }
    public void setText(String text) {
        this.text = text;
    }
}

class Clicked {
    private String action;
    private String value;

    public String getAction() {
        return action;
    }
    public void setAction(String action) {
        this.action = action;
    }
    public String getValue() {
        return value;
    }
    public void setValue(String value) {
        this.value = value;
    }
}

class Hover {
    private String action;
    private String value;

    public String getAction() {
        return action;
    }
    public void setAction(String action) {
        this.action = action;
    }
    public String getValue() {
        return value;
    }
    public void setValue(String value) {
        this.value = value;
    }
}

Я изменил это, чтобы показать весь код

public class With {
    private String translate;
    private Clicked clickEvent;
    private Hover hoverEvent;
    private String insertion;
    private String text = "";

    //setter and getters

    public ChatMessage getNonNull(ChatMessage mes){
        if(this.text != null)mes.setText(this.text);
        if(this.translate != null)mes.setTranslate(this.translate);
        if(this.score != null)mes.setScore(this.score);
        if(this.selector != null)mes.setSelector(this.selector);
        if(this.extra != null)mes.setExtra(this.extra);
        if(this.bold != null)mes.setBold(this.bold);
        if(this.italic != null)mes.setItalic(this.italic);
        if(this.underlined != null)mes.setUnderlined(this.underlined);
        if(this.strikethrough != null)mes.setStrikethrough(this.strikethrough);
        if(this.obfuscated != null)mes.setObfuscated(this.obfuscated);
        if(this.color != null)mes.setColor(this.color);
        if(this.clickEvent != null)mes.setClickEvent(this.clickEvent);
        if(this.hoverEvent != null)mes.setHoverEvent(this.hoverEvent);
        if(this.insertion != null)mes.setInsertion(this.insertion);
        return mes;
    }
}

Теперь проблема в том, что когда Gson пытается проанализировать это, он, конечно, сталкивается с проблемой, что вторая часть массива «with» НЕ является объектом With. Моя проблема в том, что я понятия не имею, как с этим бороться. Любая помощь будет принята с благодарностью.

Edit1 Что он должен делать: массив with просто предполагает своего рода «перезапись», так как любое поле из основной строки может быть перезаписано и индивидуально отформатировано внутри. Это то, что должна делать нулевая вещь в нижней части класса With, предполагается, что она редактирует основные переменные с их перезаписанным содержимым. Предполагается, что безымянное поле здесь является текстовой переменной.


person woder    schedule 04.04.2015    source источник
comment
Что вы хотите получить с этим привет значением? Сохранить в списке? Выбросить?   -  person Alexis C.    schedule 05.04.2015
comment
О да, я пытаюсь поместить его в переменную, в данном случае текстовую переменную (это фактический текст, а остальное здесь — форматирование), если это поможет, вот документация по фактической строке json, используемой здесь: wiki.vg/Chat   -  person woder    schedule 05.04.2015
comment
Документация, на которую вы ссылаетесь, не показывает эту конкретную структуру (говоря о массиве with). В любом случае вы можете написать собственный десериализатор для анализа этого JSON по своему усмотрению.   -  person Alexis C.    schedule 05.04.2015
comment
Есть ли шанс, что вы могли бы поставить меня на правильный путь для этого? Я новичок в Gson.   -  person woder    schedule 05.04.2015
comment
Конечно, но я не очень уверен в том, какая окончательная структура вам нужна, поэтому, если бы вы могли прояснить некоторые вещи, это помогло бы.   -  person Alexis C.    schedule 05.04.2015
comment
Я отредактировал свой вопрос, чтобы включить более подробную информацию о том, что должно происходить. Я считаю, что то, что я написал, должно охватывать все. Кстати, спасибо!   -  person woder    schedule 05.04.2015
comment
Кажется, я понимаю, что он должен дать. Но говоря о вашей первоначальной проблеме, эта строка hi должна храниться в какой переменной? Я не вижу, где это было бы во всей структуре, которую вы даете.   -  person Alexis C.    schedule 05.04.2015
comment
Переменная называется Text.   -  person woder    schedule 05.04.2015
comment
Есть несколько переменных, называемых текстом. Ты говоришь о той, что в классе В? Но разве это не должно быть woder22, а тот, что в ChatMessage, не должен быть Hello world (в приведенном вами примере). Эта приветственная строка нигде не появляется в вашей структуре, если я действительно не слепой...   -  person Alexis C.    schedule 05.04.2015
comment
Ого, а я и не заметил! Хорошо, извините за путаницу! Привет — это на самом деле сообщение чата, поэтому я полагаю, что было бы справедливо назвать его текстом чата, который будет расположен внутри класса With (поскольку именно там мы анализируем эту часть строки). Однако вы заставили меня понять, что привет нигде не появляется, что интересно.   -  person woder    schedule 05.04.2015
comment
Но это массив экземпляров With, поэтому его следует поместить в первый элемент массива. В настоящее время структура имеет вид [С объектом, String hi].   -  person Alexis C.    schedule 05.04.2015
comment
Да, видите, это возвращение к исходной проблеме. Предполагается, что каждый элемент в массиве with перезаписывает материал в ChatMessage. При этом, когда это с объектом, все внутри объекта должно перезаписывать соответствующее значение в сообщении чата. В случае, когда оно там случайно, как и в случае с приветом, оно должно просто переопределять соответствующее поле. (Обратите внимание, что я не контролирую строку json и не знаю, почему это было сделано именно так)   -  person woder    schedule 05.04.2015
comment
Сначала поговорим о разборе. Когда у вас будет это, вы сможете перезаписать то, что вам нужно перезаписать. with может быть List‹Object› с некоторыми экземплярами With или String hi. Если вас это устраивает, я могу показать вам, как это получить. Но я не уверен, что вы хотите делать с этой строкой. Цель состоит в том, чтобы заменить текстовое значение в объекте? Но уже есть текстовое значение, которое перезаписывается в объекте With, что сбивает с толку. Так что же должно делать это значение hi?   -  person Alexis C.    schedule 05.04.2015
comment
Если быть до конца честным, я тоже как бы догадываюсь об этой части, однако я знаю, что конечный результат должен выглядеть следующим образом: ‹woder22› привет, теперь, как это на самом деле достигается, для меня не имеет большого значения. Однако из моих наблюдений следует, что текстовая переменная (woder22) кажется именем пользователя, а значение noname (привет) кажется фактическим сообщением.   -  person woder    schedule 05.04.2015


Ответы (1)


Вот как вы можете написать собственный десериализатор для этого:

class ChatMessageDezerializer implements JsonDeserializer<ChatMessage> {
    @Override
    public ChatMessage deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
        ChatMessage message = new ChatMessage();
        JsonObject obj = json.getAsJsonObject();
        message.translate = obj.get("translate").getAsString();
        JsonArray array = obj.getAsJsonArray("with");
        message.with.add(context.deserialize(array.get(0), With.class));
        message.with.add(array.get(1).getAsString());
        return message;
    }
}

и зарегистрируйте его в своем парсере Gson:

Gson gson = new GsonBuilder().registerTypeAdapter(ChatMessage.class, new ChatMessageDezerializer()).create();

Обратите внимание, что with теперь является List<Object>, поскольку наиболее специфическим общим типом для элементов в массиве является Object. Также я только что сделал проблемную часть, с остальным можно справиться легко. Запустив это, вы получите

[With@b1a58a3, hi]

как результирующий список. Это предполагает, что у вас есть минимальный контроль над структурой, которую вы возвращаете (или, по крайней мере, вы знаете, в каком формате она будет). Это должно дать вам хорошую отправную точку оттуда.

person Alexis C.    schedule 04.04.2015
comment
@Alexis, не могли бы вы рассказать мне что-нибудь об универсальном типе, как вы реализовали в коде, я мало знаю (например, как использовать в ArrayList‹String›) о них и хочу научиться работать с дженериками - person Pankaj Nimgade; 06.04.2015