Преобразование из Json в несколько типов с одной функцией - PullRequest
0 голосов
/ 02 ноября 2019

Я написал приложение Java, где данные были получены из API в JSON. В зависимости от конечной точки фактические данные могут быть очень разными. Поэтому я сделал функцию для преобразования данных в требуемый класс для каждого возможного класса. Это дает мне несколько функций, которые отличаются только по классу, в который нужно конвертировать. Ниже приведены два примера:

public List<ZermeloBranch> processBranches(ZermeloApiResponseObject responseObject) {
        List<ZermeloBranch> branches = new ArrayList<>();
        List<LinkedTreeMap> branchMaps = responseObject.getData();
        Gson gson = new Gson();
        for (LinkedTreeMap treeMap : branchMaps) {
            branches.add(gson.fromJson(gson.toJsonTree(treeMap).toString(), ZermeloBranch.class));
        }
        return branches;
    }

public List<ZermeloAnnouncement> processAnnouncements(ZermeloApiResponseObject responseObject) {
        List<ZermeloAnnouncement> announcements = new ArrayList<ZermeloAnnouncement>();
        List<LinkedTreeMap> announcementMaps = responseObject.getData();
        Gson gson = new Gson();
        for (LinkedTreeMap treeMap : announcementMaps) {
            announcements.add(gson.fromJson(gson.toJsonTree(treeMap).toString(), ZermeloAnnouncement.class));
        }
        return announcements;
    }

Теперь я переписываю это приложение в Kotlin, и я полагаю, что должна быть возможность написать одну функцию для обработки данных, передающих класс для декодирования в качестве параметра. Поэтому я сделал наследование ZermeloBranch и ZermeloAnnouncement от ZermeloDataObject. Я хотел бы написать одну функцию, подобную этой:

fun processDataToList(data:JSONArray, convertToClass:KClass<out ZermeloDataObject>):List<KClass<out ZermeloDataObject>>{
    val returnList:ArrayList<KClass<out ZermeloDataObject>> = arrayListOf()
    val gson = Gson()
    for (item in 0 until data.length()){
        returnList.add(gson.fromJson(item, convertToClass))
    }
    return returnList
}

и вызвать ее с помощью processDataToList(data, ZermeloAnnouncements::class) и получить List<ZermeloAnnoucement> возвращенный результат вызова с processDataToList(data, ZermeloBranch::class) и получить возвращенный List<ZermeloBranch>. Увы, компилятор выдает мне ошибку на gson.fromJson, утверждая, что «ни одна из следующих функций не может быть вызвана с предоставленными аргументами», а затем перечисляет все возможные функции.

Можно ли использовать одну функцию как Iпредложите, и если да, что я делаю не так?

1 Ответ

1 голос
/ 02 ноября 2019

Вы можете использовать TypeToken, предоставленный Gson для правильной обработки возвращаемого типа. Помимо этого вы передаете index вместо данных .

val type = object: TypeToken<KClass<out ZermeloDataObject>>() {}.type

fun processDataToList(data:JSONArray, convertToClass:KClass<out ZermeloDataObject>):ArrayList<KClass<out ZermeloDataObject>>{
    val returnList:ArrayList<KClass<out ZermeloDataObject>> = arrayListOf()
    val type = object: TypeToken<KClass<out ZermeloDataObject>>() {}.type
    val gson = Gson()

    for (item in 0 until data.length()){
        returnList.add(gson.fromJson(data[item].toString(), type))
    }

    return returnList
}

Вместоэто вы можете сделать все это в одной строке кода. Проверьте ниже:

fun processDataToList(data:JSONArray, convertToClass:KClass<out ZermeloDataObject>):List<KClass<out ZermeloDataObject>>{
    return Gson().fromJson(data.toString(), object: TypeToken<List<KClass<out ZermeloDataObject>>>() {}.type)
}

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

fun <T> processDataToList(data:JSONArray): List<T> {
    val type = object: TypeToken<T>() {}.type
    val returnList: ArrayList<T> = arrayListOf()
    val gson = Gson()

    for (item in 0 until data.length()) {
        returnList.add(gson.fromJson(json[item].toString(), type))
    }

    return returnList
}

Или просто

fun <T> processDataToList(data:JSONArray):List<T>{
    return Gson().fromJson(data.toString(), object: TypeToken<List<T>>() {}.type)
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...