Merge pull request #5 from banjjoknim/jackson
ContextualSerializer 를 사용하는 직렬화 예제 코드 추가
This commit is contained in:
@@ -1,5 +1,6 @@
|
|||||||
package com.banjjoknim.playground.jackson.common
|
package com.banjjoknim.playground.jackson.common
|
||||||
|
|
||||||
|
import com.banjjoknim.playground.jackson.jsonserialize.ContextualCarSerializer
|
||||||
import com.banjjoknim.playground.jackson.jsonserialize.UsingJsonSerializeAnnotationCarSerializer
|
import com.banjjoknim.playground.jackson.jsonserialize.UsingJsonSerializeAnnotationCarSerializer
|
||||||
import com.fasterxml.jackson.databind.annotation.JsonSerialize
|
import com.fasterxml.jackson.databind.annotation.JsonSerialize
|
||||||
|
|
||||||
@@ -16,7 +17,7 @@ data class CarUsingNoAnnotation(
|
|||||||
val owner: Owner = Owner()
|
val owner: Owner = Owner()
|
||||||
)
|
)
|
||||||
|
|
||||||
data class CarUsingJsonSerializeAnnotation(
|
data class CarUsingJsonSerializeAnnotationCarSerializer(
|
||||||
val name: String = "banjjoknim",
|
val name: String = "banjjoknim",
|
||||||
@JsonSerialize(using = UsingJsonSerializeAnnotationCarSerializer::class)
|
@JsonSerialize(using = UsingJsonSerializeAnnotationCarSerializer::class)
|
||||||
val secret: String = "secret",
|
val secret: String = "secret",
|
||||||
@@ -24,6 +25,23 @@ data class CarUsingJsonSerializeAnnotation(
|
|||||||
val owner: Owner = Owner()
|
val owner: Owner = Owner()
|
||||||
)
|
)
|
||||||
|
|
||||||
|
data class CarUsingContextualSerializerWithSecretAnnotation(
|
||||||
|
val name: String = "banjjoknim",
|
||||||
|
@JsonSerialize(using = ContextualCarSerializer::class)
|
||||||
|
@field:Secret("hello world!!")
|
||||||
|
val secret: String = "secret",
|
||||||
|
val price: Int = 10000000,
|
||||||
|
val owner: Owner = Owner()
|
||||||
|
)
|
||||||
|
|
||||||
|
data class CarUsingContextualSerializerWithNoSecretAnnotation(
|
||||||
|
val name: String = "banjjoknim",
|
||||||
|
@JsonSerialize(using = ContextualCarSerializer::class)
|
||||||
|
val secret: String = "secret",
|
||||||
|
val price: Int = 10000000,
|
||||||
|
val owner: Owner = Owner()
|
||||||
|
)
|
||||||
|
|
||||||
data class CarUsingSecretAnnotation(
|
data class CarUsingSecretAnnotation(
|
||||||
val name: String = "banjjoknim",
|
val name: String = "banjjoknim",
|
||||||
@field:Secret("****")
|
@field:Secret("****")
|
||||||
|
|||||||
@@ -4,6 +4,8 @@ import com.banjjoknim.playground.jackson.common.Car
|
|||||||
import com.banjjoknim.playground.jackson.common.Secret
|
import com.banjjoknim.playground.jackson.common.Secret
|
||||||
import com.fasterxml.jackson.core.JsonGenerator
|
import com.fasterxml.jackson.core.JsonGenerator
|
||||||
import com.fasterxml.jackson.databind.BeanDescription
|
import com.fasterxml.jackson.databind.BeanDescription
|
||||||
|
import com.fasterxml.jackson.databind.BeanProperty
|
||||||
|
import com.fasterxml.jackson.databind.JsonSerializer
|
||||||
import com.fasterxml.jackson.databind.SerializationConfig
|
import com.fasterxml.jackson.databind.SerializationConfig
|
||||||
import com.fasterxml.jackson.databind.SerializerProvider
|
import com.fasterxml.jackson.databind.SerializerProvider
|
||||||
import com.fasterxml.jackson.databind.introspect.Annotated
|
import com.fasterxml.jackson.databind.introspect.Annotated
|
||||||
@@ -12,6 +14,7 @@ import com.fasterxml.jackson.databind.introspect.JacksonAnnotationIntrospector
|
|||||||
import com.fasterxml.jackson.databind.module.SimpleModule
|
import com.fasterxml.jackson.databind.module.SimpleModule
|
||||||
import com.fasterxml.jackson.databind.ser.BeanPropertyWriter
|
import com.fasterxml.jackson.databind.ser.BeanPropertyWriter
|
||||||
import com.fasterxml.jackson.databind.ser.BeanSerializerModifier
|
import com.fasterxml.jackson.databind.ser.BeanSerializerModifier
|
||||||
|
import com.fasterxml.jackson.databind.ser.ContextualSerializer
|
||||||
import com.fasterxml.jackson.databind.ser.std.StdSerializer
|
import com.fasterxml.jackson.databind.ser.std.StdSerializer
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -83,6 +86,24 @@ class UsingJsonSerializeAnnotationCarSerializer : StdSerializer<String>(String::
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class ContextualCarSerializer(
|
||||||
|
private val substituteValue: String = "this is default value in ContextualCarSerializer"
|
||||||
|
) : StdSerializer<String>(String::class.java), ContextualSerializer {
|
||||||
|
override fun serialize(value: String, gen: JsonGenerator, provider: SerializerProvider) {
|
||||||
|
gen.writeString(substituteValue)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun createContextual(provider: SerializerProvider, property: BeanProperty): JsonSerializer<*> {
|
||||||
|
val annotation = property.getAnnotation(Secret::class.java)
|
||||||
|
if (annotation != null) {
|
||||||
|
return ContextualCarSerializer(annotation.substituteValue)
|
||||||
|
}
|
||||||
|
return ContextualCarSerializer()
|
||||||
|
// JsonMappingException: Can not write a field name, expecting a value (through reference chain: com.banjjoknim.playground.jackson.common.CarUsingContextualSerializerWithNoSecretAnnotation["secret"])
|
||||||
|
// return provider.findKeySerializer(property.type, property)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* AnnotationIntrospector 를 상속한 JacksonAnnotationIntrospector 은 Jackson 라이브러리가 직렬화/역직렬화시 `JacksonAnnotation` 정보를 어떻게 처리할지에 대한 정보가 정의되어 있는 클래스다.
|
* AnnotationIntrospector 를 상속한 JacksonAnnotationIntrospector 은 Jackson 라이브러리가 직렬화/역직렬화시 `JacksonAnnotation` 정보를 어떻게 처리할지에 대한 정보가 정의되어 있는 클래스다.
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -1,7 +1,9 @@
|
|||||||
package com.banjjoknim.playground.jackson.jsonserialize
|
package com.banjjoknim.playground.jackson.jsonserialize
|
||||||
|
|
||||||
import com.banjjoknim.playground.jackson.common.Car
|
import com.banjjoknim.playground.jackson.common.Car
|
||||||
import com.banjjoknim.playground.jackson.common.CarUsingJsonSerializeAnnotation
|
import com.banjjoknim.playground.jackson.common.CarUsingContextualSerializerWithNoSecretAnnotation
|
||||||
|
import com.banjjoknim.playground.jackson.common.CarUsingContextualSerializerWithSecretAnnotation
|
||||||
|
import com.banjjoknim.playground.jackson.common.CarUsingJsonSerializeAnnotationCarSerializer
|
||||||
import com.banjjoknim.playground.jackson.common.CarUsingNoAnnotation
|
import com.banjjoknim.playground.jackson.common.CarUsingNoAnnotation
|
||||||
import com.banjjoknim.playground.jackson.common.CarUsingSecretAnnotation
|
import com.banjjoknim.playground.jackson.common.CarUsingSecretAnnotation
|
||||||
import com.banjjoknim.playground.jackson.common.Owner
|
import com.banjjoknim.playground.jackson.common.Owner
|
||||||
@@ -32,7 +34,11 @@ class CarSerializersTest {
|
|||||||
private val owner = Owner("ban", 30)
|
private val owner = Owner("ban", 30)
|
||||||
private val car = Car("banjjoknim", 10_000_000, owner)
|
private val car = Car("banjjoknim", 10_000_000, owner)
|
||||||
private val carUsingNoAnnotation = CarUsingNoAnnotation()
|
private val carUsingNoAnnotation = CarUsingNoAnnotation()
|
||||||
private val carUsingJsonSerializeAnnotation = CarUsingJsonSerializeAnnotation()
|
private val carUsingJsonSerializeAnnotationCarSerializer = CarUsingJsonSerializeAnnotationCarSerializer()
|
||||||
|
private val carUsingContextualSerializerWithSecretAnnotation =
|
||||||
|
CarUsingContextualSerializerWithSecretAnnotation()
|
||||||
|
private val carUsingContextualSerializerWithNoSecretAnnotation =
|
||||||
|
CarUsingContextualSerializerWithNoSecretAnnotation()
|
||||||
private val carUsingSecretAnnotation = CarUsingSecretAnnotation()
|
private val carUsingSecretAnnotation = CarUsingSecretAnnotation()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -141,12 +147,26 @@ class CarSerializersTest {
|
|||||||
// given
|
// given
|
||||||
|
|
||||||
// when
|
// when
|
||||||
val actual = mapper.writeValueAsString(carUsingJsonSerializeAnnotation)
|
val actual = mapper.writeValueAsString(carUsingJsonSerializeAnnotationCarSerializer)
|
||||||
|
|
||||||
// then
|
// then
|
||||||
assertThat(actual).isEqualTo("""{"name":"banjjoknim","secret":"****","price":10000000,"owner":{"name":"ban","age":30}}""")
|
assertThat(actual).isEqualTo("""{"name":"banjjoknim","secret":"****","price":10000000,"owner":{"name":"ban","age":30}}""")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `ContextualSerializer 를 상속 받은 구현체를 이용해서 직렬화한다`() {
|
||||||
|
// given
|
||||||
|
|
||||||
|
// when
|
||||||
|
val actualWithSecretAnnotation = mapper.writeValueAsString(carUsingContextualSerializerWithSecretAnnotation)
|
||||||
|
val actualWithNoSecretAnnotation =
|
||||||
|
mapper.writeValueAsString(carUsingContextualSerializerWithNoSecretAnnotation)
|
||||||
|
|
||||||
|
// then
|
||||||
|
assertThat(actualWithSecretAnnotation).isEqualTo("""{"name":"banjjoknim","secret":"hello world!!","price":10000000,"owner":{"name":"ban","age":30}}""")
|
||||||
|
assertThat(actualWithNoSecretAnnotation).isEqualTo("""{"name":"banjjoknim","secret":"this is default value in ContextualCarSerializer","price":10000000,"owner":{"name":"ban","age":30}}""")
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `@Secret 어노테이션, AnnotationIntrospector 을 적용하여 직렬화한다`() {
|
fun `@Secret 어노테이션, AnnotationIntrospector 을 적용하여 직렬화한다`() {
|
||||||
// given
|
// given
|
||||||
@@ -239,7 +259,10 @@ class CarSerializersTest {
|
|||||||
|
|
||||||
// when
|
// when
|
||||||
mapper.setAnnotationIntrospector(
|
mapper.setAnnotationIntrospector(
|
||||||
AnnotationIntrospector.pair(SecretAnnotationIntrospector(), originalAnnotationIntrospector) // 내부 구현은 아래와 같다.
|
AnnotationIntrospector.pair(
|
||||||
|
SecretAnnotationIntrospector(),
|
||||||
|
originalAnnotationIntrospector
|
||||||
|
) // 내부 구현은 아래와 같다.
|
||||||
// AnnotationIntrospectorPair(SecretAnnotationIntrospector(), originalAnnotationIntrospector)
|
// AnnotationIntrospectorPair(SecretAnnotationIntrospector(), originalAnnotationIntrospector)
|
||||||
)
|
)
|
||||||
val allIntrospectorNames = mapper.serializationConfig.annotationIntrospector.allIntrospectors()
|
val allIntrospectorNames = mapper.serializationConfig.annotationIntrospector.allIntrospectors()
|
||||||
|
|||||||
Reference in New Issue
Block a user