Как десериализовать строку json в массив - PullRequest
0 голосов
/ 07 июня 2018

У меня следующий JSON.

{
"code": 200,
"status": "success",
"request": [],
"total": 10,
"count": 10,
"offset": 0,
"limit": 100,
"response": [
    {
        "uid": "doc-1",
        "name": "Иванов Иван Иванович",
        "spec": [
            "Врач лабораторной диагностики",
            "Врач-терапевт"
        ],
        "photo": "http://demo-api.atlas-patiente.office.prosvdigital.ru/img/doctor/01.jpg"
    },
    {
        "uid": "doc-10",
        "name": "Попов Евгений Олегович",
        "spec": [
            "Врач ренгенолог"
        ],
        "photo": "http://demo-api.atlas-patiente.office.prosvdigital.ru/img/doctor/10.jpg"
    },
    {
        "uid": "doc-2",
        "name": "Петров Сергей Иванович",
        "spec": [
            "Врач лабораторной диагностики",
            "Врач диетолог",
            "врач-терапевт"
        ],
        "photo": "http://demo-api.atlas-patiente.office.prosvdigital.ru/img/doctor/02.jpg"
    },
    {
        "uid": "doc-3",
        "name": "Сидоров Сергей Константинович",
        "spec": [
            "Врач лабораторной диагностики",
            "Врач - ренгенолог"
        ],
        "photo": "http://demo-api.atlas-patiente.office.prosvdigital.ru/img/doctor/03.jpg"
    },
    {
        "uid": "doc-4",
        "name": "Константинов Александр Константинович",
        "spec": [
            "Врач лабораторной диагностики",
            "Врач-терапевт"
        ],
        "photo": "http://demo-api.atlas-patiente.office.prosvdigital.ru/img/doctor/04.jpg"
    },
    {
        "uid": "doc-5",
        "name": "Сергеев Иван Константинович",
        "spec": "Врач лабораторной диагностики",
        "photo": "http://demo-api.atlas-patiente.office.prosvdigital.ru/img/doctor/05.jpg"
    },
    {
        "uid": "doc-6",
        "name": "Попов Дмитрий Данилович",
        "spec": [
            "Врач лабораторной диагностики",
            "Врач ренгенолог"
        ],
        "photo": "http://demo-api.atlas-patiente.office.prosvdigital.ru/img/doctor/06.jpg"
    },
    {
        "uid": "doc-7",
        "name": "Иванова Екатерина Павловна",
        "spec": [
            "Врач терапевт"
        ],
        "photo": "http://demo-api.atlas-patiente.office.prosvdigital.ru/img/doctor/07.jpg"
    },
    {
        "uid": "doc-8",
        "name": "Екатеринина Лада Павловна",
        "spec": [
            "Врач терапевт"
        ],
        "photo": "http://demo-api.atlas-patiente.office.prosvdigital.ru/img/doctor/08.jpg"
    },
    {
        "uid": "doc-9",
        "name": "Васильева Екатерина Олеговна",
        "spec": [
            "Врач терапевт"
        ],
        "photo": "http://demo-api.atlas-patiente.office.prosvdigital.ru/img/doctor/09.jpg"
    }
  ]
}

Как видите, все поля spec являются массивом, кроме одного - doc-5.Я получаю с данными в Retrofit.Это мой POJO для этого ответа.

public class Doctor implements IDObject<String>, Serializable {

public static final String FIELD_NAME = "name";

@SerializedName("uid")
private String id;
@SerializedName("name")
private String name;
@SerializedName("doctorShortName")
private String shortName;
@SerializedName("spec")
private List<String> speciality;
@SerializedName("photo")
private String photoUrl;

public String getName() {
    return name;
}

public String getPhotoUrl() {
    return photoUrl;
}

public List<String> getSpeciality() {
    return speciality;
}

public String getShortName() {
    return shortName;
}

@Override
public String getId() {
    return id;
}

@Override
public int hashCode() {
    return getId().hashCode();
}

@Override
public boolean equals(Object obj) {
    return obj instanceof Doctor && ((Doctor) obj).getId().equals(getId());
}
}

Каждый раз, когда я пытаюсь разобрать это = ошибка.Но если я сделаю поле spec в doc-5 String = все хорошо!

Но я не знаю, какой сервер ответов может мне отправить, потому что у доктора может быть только одна специальность (в данном случае specбудет строкой) или он может иметь два и более (в данном случае spec будет массивом).

И как мне создать многоцелевой десериализатор, который будет работать в обоих случаях?

Ответы [ 2 ]

0 голосов
/ 07 июня 2018

Я нашел решение своей проблемы.Прежде всего - добавьте аннотацию @Expose к spec, поданному в классе Doctor POJO, и добавьте установщик для spec.

public class Doctor implements IDObject<String>, Serializable {

public static final String FIELD_NAME = "name";

@SerializedName("uid")
private String id;
@SerializedName("name")
private String name;
@SerializedName("doctorShortName")
private String shortName;
@Expose(deserialize = false)
private List<String> speciality;
@SerializedName("photo")
private String photoUrl;

public String getName() {
    return name;
}

public String getPhotoUrl() {
    return photoUrl;
}

public List<String> getSpeciality() {
    return speciality;
}

public String getShortName() {
    return shortName;
}

@Override
public String getId() {
    return id;
}

@Override
public int hashCode() {
    return getId().hashCode();
}

@Override
public boolean equals(Object obj) {
    return obj instanceof Doctor && ((Doctor) obj).getId().equals(getId());
}

public void setSpeciality(List<String> speciality) {
    this.speciality = speciality;
}
}

Добавьте десериализатор

public class FooDeserializer implements JsonDeserializer<Doctor> {

@Override
public Doctor deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
    Type type = new TypeToken<DoctorChild>() {}.getType();

    Doctor foo = context.deserialize(json, type);

    JsonElement specField = json.getAsJsonObject().get("spec");

    if (specField != null && !specField.isJsonNull()) {

        List<String> specs = new ArrayList<>();

        if (specField.isJsonArray()) {
            JsonArray specList = specField.getAsJsonArray();
            Iterator<JsonElement> iterator = specList.iterator();
            while (iterator.hasNext()) {
                JsonElement element = iterator.next();
                String spec = element != null && !element.isJsonNull() ? element.getAsString() : null;
                specs.add(spec);
            }
        } else if (specField.isJsonPrimitive()) {
            JsonPrimitive specPrimitive = specField.getAsJsonPrimitive();
            if (specPrimitive.isString()) {
                String spec = specPrimitive.getAsString();
                specs.add(spec);
            }
        }

        foo.setSpeciality(specs);

    }

    return foo;
}
}

Ипосле этого добавьте его в GsonConfiguration

private static GsonBuilder base() {
    return new GsonBuilder()
            .addSerializationExclusionStrategy(new SerializeExclusionStrategy())
            .addDeserializationExclusionStrategy(new DeserializeExclusionStrategy())
            .registerTypeAdapter(Doctor.class, new FooDeserializer())
}
0 голосов
/ 07 июня 2018

Если у вас есть единственная строка spec asi, и List / Array поступает с сервера, происходит ли сбой приложения или в строке содержится json этого List / Array?Если это произойдет, то будет достаточно просто проанализировать его с помощью Gson или любого другого фреймворка, который вы используете.

Добавил бы это как комментарий, но еще не набрал репутацию, извините.

...