Как уменьшить аналогичный код, который опирается на тип класса для родителя? - PullRequest
0 голосов
/ 05 июля 2018

Я использую Jackson-Kotlin для сериализации и десериализации объектов JSON в моем проекте kotlin. Проблема в том, что мне нужно определить один и тот же метод в каждом классе, изменив только одно typeValue. Это кажется очень плохой практикой, поэтому я прихожу к сообществу, чтобы узнать, как лучше всего справиться с этим сценарием.

Пример:

class User: Model() {
    //...
    companion object {

        fun fromJson(json: String): User {
            return ObjectMapper().registerKotlinModule().readValue<User>(json)
        }

        fun toJson(user: User): String {
            return ObjectMapper().registerKotlinModule().writeValueAsString(user)
        }


    }
}

class Friend: Model() {
    //...
    companion object {

        fun fromJson(json: String): User {
            return ObjectMapper().registerKotlinModule().readValue<Friend>(json)
        }

        fun toJson(friend: Friend): String {
            return ObjectMapper().registerKotlinModule().writeValueAsString(user)
        }


    }
}

Как видите, код очень похож, кроме параметра типа в методе readValue<>(). Есть ли способ, которым я могу просто определить один метод в классе Model () вместо каждого класса, который наследуется от Model?

Ответы [ 2 ]

0 голосов
/ 06 июля 2018

Вы не хотите создавать ObjectMapper и регистрировать модуль каждый раз.

class Model {
    companion object {
        // could be public if you want to do anything else with it
        private val objectMapper = ObjectMapper().registerKotlinModule()

        inline fun <reified T : Model> fromJson(json: String): User {
            return objectMapper.readValue<T>(json)
        }

        fun toJson(value: Model): String {
            return objectMapper.writeValueAsString(value)
        }
    }
}

Использование:

val friend = Model.fromJson<Friend>(...)

или просто Model.fromJson(...), когда есть ожидаемый тип.

Также с той же страницы:

Ввод: лучше использовать байт [], если он у вас есть; InputStream второй лучший; за ним следует Reader - и в любом случае, НЕ пытайтесь читать входные данные в String!

Вывод: OutputStream является лучшим; Писатель второй лучший; и вызов writeValueAsString () наименее эффективен (зачем создавать промежуточную строку?)

0 голосов
/ 06 июля 2018

Похоже, вы можете использовать генериков здесь.

Объекты-компаньоны не имеют представления о типовых аргументах класса, так как они не являются экземплярами класса, поэтому вы можете либо сделать ваши методы экземпляров функций наследуемыми:

class Model<T> {
    fun fromJson(json: String): User {
        return ObjectMapper().registerKotlinModule().readValue<T>(json)
    }

    fun toJson(friend: T): String {
        return ObjectMapper().registerKotlinModule().writeValueAsString(friend)
    }
}

или пусть сами функции принимают параметры типа:

class Model {
    companion object {
        fun <T> fromJson(json: String): User {
            return ObjectMapper().registerKotlinModule().readValue<T>(json)
        }

        fun <T> toJson(friend: T): String {
            return ObjectMapper().registerKotlinModule().writeValueAsString(friend)
        }
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...