Предложение (я) по десериализации Json объектов, которые имеют некоторые атрибуты с типом динамического c с gson - PullRequest
2 голосов
/ 11 июля 2020

Я хочу десериализовать следующий объект:

{
  "qid": "226",
  "parent_qid": "225",
  "sid": "298255",
  "gid": "25",
  "type": "M",
  "title": "SQ001",
  "question": "question text",
  "preg": null,
  "help": null,
  "other": "N",
  "mandatory": null,
  "question_order": "1",
  "language": "de",
  "scale_id": "0",
  "same_default": "0",
  "relevance": "1",
  "modulename": "",
  "available_answers": "No available answers",
  "subquestions": "No available answers",
  "attributes": "No available attributes",
  "attributes_lang": "No available attributes",
  "answeroptions": "No available answer options",
  "defaultvalue": null
}

Члены с типами:

private HashMap<String, String> available_answers;

private HashMap<Integer, SubQuestion> subquestions;

Моя проблема в том, что в некоторых случаях атрибуты «answeroptions» и «available_answers» ( возможно, еще один или два) не просто строки, а другие объекты.

A) Я читал о создании настраиваемого десериализатора для обработки таких случаев, но это привело бы к тому, что мне также пришлось бы десериализовать другой атрибуты с типами stati c (больше ненужного кода).

B) Другой подход, который пришел мне в голову, заключается в том, что я мог «десериализовать» атрибуты в JsonObjects и полностью десериализовать их в соответствующих геттерах.

Итак, мой вопрос в том, можете ли вы предложить мне подход а), б) или другой.

Приветствую и заранее спасибо!

1 Ответ

0 голосов
/ 26 августа 2020

Если эти поля имеют только строковое значение JSON, если они имеют нет значения , тогда вы можете использовать аннотацию @JsonAdapter и пользовательский TypeAdapterFactory :

/**
 * Only for use on fields annotated with {@code @JsonAdapter}.
 */
public class StringAsNullTypeAdapterFactory implements TypeAdapterFactory {
    @Override
    public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> type) {
        TypeAdapter<T> delegate = gson.getAdapter(type);
        return new TypeAdapter<T>() {
            @Override
            public void write(JsonWriter out, Object value) throws IOException {
                // You will have to implement this in case you are
                // also writing JSON data
                throw new UnsupportedOperationException();
            }
            
            @Override
            public T read(JsonReader in) throws IOException {
                if (in.peek() == JsonToken.STRING) {
                    in.skipValue(); // skip the string
                    return null;
                }
                return delegate.read(in);
            }
        };
    }
}

Затем вы можете использовать этот TypeAdapterFactory следующим образом:

class Quiz {
    public String qid;
    public String parent_qid;
    
    // ...
    
    @JsonAdapter(StringAsNullTypeAdapterFactory.class)
    public HashMap<String, String> available_answers;
    @JsonAdapter(StringAsNullTypeAdapterFactory.class)
    public HashMap<Integer, SubQuestion> subquestions;
}

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

...