잭슨을 사용하여 Kotlin 컬렉션을 역직렬화하는 방법
원하는 샘플 코드:
data class D(val a: String, val b: Int)
val jsonStr = """[{"a": "value1", "b": 1}, {"a": "value2", "b":"2}]"""
// what I need
val listOfD: List<D> = jacksonObjectMapper().whatMethodAndParameter?
Jackson Kotlin 모듈의 최신 버전에서 풀 모듈 패키지 또는 특정 확장 기능을 가져오면 모든 확장 방법을 사용할 수 있습니다.예를 들어 다음과 같습니다.
import com.fasterxml.jackson.module.kotlin.*
val JSON = jacksonObjectMapper() // keep around and re-use
val myList: List<String> = JSON.readValue("""["a","b","c"]""")
따라서 Jackson Module for Kotlin은 올바른 유형을 추론할 수 있으며, 사용자는 이 유형을 추론할 필요가 없습니다.TypeReference
사례.
따라서 (약간 데이터 클래스 이름 변경 및 수정, JSON)은 다음과 같습니다.
import com.fasterxml.jackson.module.kotlin.readValue
data class MyData(val a: String, val b: Int)
val JSON = jacksonObjectMapper()
val jsonStr = """[{"a": "value1", "b": 1}, {"a": "value2", "b": 2}]"""
val myList: List<MyData> = JSON.readValue(jsonStr)
다음의 폼도 사용할 수 있습니다.
val myList = JSON.readValue<List<MyData>>(jsonStr)
Import를 하지 않으면 확장 함수를 찾을 수 없기 때문에 오류가 발생합니다.
TL;DR
잭슨이랑2.6.3-2
@syslog-minard의 조언에 따라 다음 명령을 사용합니다.
import com.fasterxml.jackson.module.kotlin.readValue
val listOfD: List<D> = jacksonMapper.readValue(jsonStr)
세부 사항
주석 없이 데이터 클래스를 역직렬화하려면 kotlin jackson 모듈이 필요하지만 컬렉션 역직렬화에는 Kotlin wrt가 특별히 필요한 것은 아닙니다.
즉, 리스트의 범용 파라미터를 추적하기 위해서는 고객의 케이스에 완전한 타입 정보가 필요합니다(D
); 그 이외의 경우(예를 들어 를 사용하는 경우)readValue(jsonStr, List::class.java)
Jackson은 그것을 지워진 유형으로만 인식합니다(즉,List
(Kotlin이 명시하고 있는 것처럼)를 디시리얼라이즈 합니다.List<Map<String, String>>
구축해야 한다는 것을 모르고 있습니다.D
s. 이는 익명의 서브클래스를 사용하여 해결됩니다.TypeReference
잭슨이 런타임에 역직렬화 대상인 전체 재작성된 유형에 액세스할 수 있도록 합니다.
Jackson Java 코드를 문자 그대로 Kotlin으로 변환하면 다음과 같이 원하는 것을 얻을 수 있습니다(@eski의 코멘트와 같이, 예의 JSON은 무효입니다).
val jacksonMapper = ObjectMapper().registerModule(KotlinModule())
val jsonStr = """[{"a": "value1", "b": 1}, {"a": "value2", "b":2}]"""
val listOfD: List<D> = jacksonMapper.readValue(jsonStr, object : TypeReference<List<D>>(){})
assertEquals(listOf(D("value1", 1), D("value2", 2)), listOfD)
이것은 약간 장황하고 보기 흉하기 때문에 Kotlin(확장) 함수(특히 여러 번 사용할 계획인 경우)에 숨길 수 있습니다.
inline fun <reified T> ObjectMapper.readValue(json: String): T = readValue(json, object : TypeReference<T>(){})
그러면 전화만 하면 됩니다.
val listOfD: List<D> = jacksonMapper.readValue(jsonStr)
그리고 이게 바로 이 제품에 포함된 내용입니다.2.6.3-2
잭슨 코틀린 모듈
일반 콘텐츠 유형이 없는 경우 다음과 같이 하십시오.<MyData>
를 참조해 주세요.
val value = context.readValue<List<MyData>>(parser, valueType)
이 기능을 구현하기 위해서는JsonSerialzier
그뿐만 아니라ContextualDeserializer
다음 코드 샘플과 같습니다(Java에서의 이 답변에 근거합니다).
class GenericListDeserializer : JsonDeserializer<List<*>>(), ContextualDeserializer {
private var valueType: JavaType? = null
override fun createContextual(ctxt: DeserializationContext, property: BeanProperty): JsonDeserializer<List<*>> {
val wrapperType = property.type
val valueType = wrapperType.containedType(0)
val deserializer = GenericListDeserializer()
deserializer.valueType = valueType
return deserializer
}
override fun deserialize(parser: JsonParser, context: DeserializationContext): List<*> {
val value :Any? = context.readValue(parser, valueType)
return listOf(value)
}
}
언급URL : https://stackoverflow.com/questions/33368328/how-to-use-jackson-to-deserialize-to-kotlin-collections
'programing' 카테고리의 다른 글
python, 파일에 Json 쓰기 (0) | 2023.02.11 |
---|---|
Angular 2에서 앱을 시작할 때 서비스를 실행하는 방법 (0) | 2023.02.11 |
다른 파일에서의 Angularjs 라우팅 (0) | 2023.02.11 |
Ajax 응답에서 반환된 JavaScript 함수 호출 (0) | 2023.02.11 |
다이내믹 ID ng-module (0) | 2023.02.11 |