Last active
June 10, 2022 13:30
-
-
Save dotNetTree/6d390aa11d6c7931a9f32cc8796b68d8 to your computer and use it in GitHub Desktop.
Code Spitz 90 - 코틀린 언어편 (2) 과제
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 1. Set도 동작하게 | |
// 2. Map도 동작하게 | |
// 3. inline 함수에 대해 조사한 뒤 최대 반영 | |
// 4. 어떤 클래스에 toJSON():String 메소드가 있다면 그 메소드를 통해 stringify를 하게 하시오 | |
@Target(AnnotationTarget.PROPERTY) | |
annotation class Ex // 제외할 속성 | |
@Target(AnnotationTarget.PROPERTY) | |
annotation class Name(val name: String) // json용 별도 이름지정 | |
fun stringify(value: Any): String = StringBuilder().run { | |
jsonValue(value) | |
toString() | |
} | |
fun StringBuilder.comma() { append(",") } | |
inline fun StringBuilder.wrap(begin: Char, end: Char, block: StringBuilder.() -> Unit) { | |
append(begin) | |
block() | |
append(end) | |
} | |
fun StringBuilder.jsonValue(value: Any?) { | |
when(value) { | |
null -> append("null") | |
is String -> jsonString(value) | |
is Boolean, is Number -> append("$value") | |
is Map<*, *> -> jsonMap(value) | |
is Array<*> -> jsonArray(value) | |
is Collection<*> -> jsonCollection(value) | |
else -> { | |
value::class.members.find { it.name == "toJSON" }.let { | |
if (it != null) append(it.call(value) as String) | |
else jsonObject(value) | |
} | |
} | |
} | |
} | |
private fun StringBuilder.jsonArray(target: Array<*>) { | |
wrap('[', ']') { | |
target.joinTo(this::comma) { | |
jsonValue(it) | |
} | |
} | |
} | |
private fun StringBuilder.jsonCollection(target: Collection<*>) { | |
wrap('[', ']') { | |
target.joinTo(this::comma) { | |
jsonValue(it) | |
} | |
} | |
} | |
private fun StringBuilder.jsonMap(target: Map<*, *>) { | |
wrap('{', '}') { | |
target.joinTo(this::comma) { k, v -> | |
jsonValue(k) | |
append(":") | |
jsonValue(v) | |
} | |
} | |
} | |
private fun StringBuilder.jsonString(v: String) = append(""""${v.replace("\"", "\\\"")}"""") | |
private fun <T: Any> StringBuilder.jsonObject(target: T) { | |
wrap('{', '}') { | |
target::class.members | |
.filterIsInstance<KProperty<*>>() | |
.filter { it.findAnnotation<Ex>() == null } | |
.joinTo(this::comma) { | |
jsonValue(it.findAnnotation<Name>()?.name ?: it.name) | |
append(":") | |
jsonValue(it.getter.call(target)) | |
} | |
} | |
} | |
inline fun <T> Array<T>.joinTo(sep:() -> Unit, transform: (T) -> Unit) { | |
forEachIndexed { idx, el -> | |
if (idx != 0) sep() | |
transform(el) | |
} | |
} | |
inline fun <T> Iterable<T>.joinTo(sep:() -> Unit, transform: (T) -> Unit) { | |
forEachIndexed { idx, el -> | |
if (idx != 0) sep() | |
transform(el) | |
} | |
} | |
inline fun <K, T> Map<K, T>.joinTo(sep:() -> Unit, transform: (K, T) -> Unit) { | |
entries.forEachIndexed { idx, el -> | |
if (idx != 0) sep() | |
val (key, value) = el | |
transform(key, value) | |
} | |
} | |
class Json1( | |
val a: Int, | |
val b: String, | |
val c: List<Int>, | |
val d: Set<String>, | |
val e: Map<Any, Any>, | |
val f: Array<String>) { } | |
class Json2(@Ex val a: Int, @Name("title") val b: String) {} | |
class Json3(val e: Map<Any, Any>) { | |
fun toJSON(): String = """{"name":"kim"} """ | |
} | |
class Json4() { | |
fun toJSON(): String = """{"a":3}""" | |
} | |
fun main(args: Array<String>) { | |
println("ready") | |
println( | |
stringify(Json1( | |
a = 3, | |
b = "abc", | |
c = arrayListOf(1,2,3), | |
d = setOf("kkk", "aaa"), | |
e = mapOf( | |
"age1" to 10, | |
"age2" to 20, | |
"props" to mapOf( | |
"name" to "kang", | |
"age" to 42, | |
"skills" to listOf("swift", "js", "ts", "kotlin", 1) | |
) | |
), | |
f = arrayOf("array", "test") | |
)) | |
) | |
println(stringify(Json2(a = 10, b = "abc"))) | |
println( | |
stringify(Json3( | |
e = mapOf( | |
"skills" to listOf("swift", "js", "ts", "kotlin", 1), | |
"props" to mapOf( | |
"name" to "kang", | |
"age" to 42, | |
"skills" to listOf("swift", "js", "ts", "kotlin", 1) | |
) | |
) | |
)) | |
) | |
println(stringify(Json4())) | |
} | |
/* 출력 | |
ready | |
{"a":3,"b":"abc","c":[1,2,3],"d":["kkk","aaa"],"e":{"age1":10,"age2":20,"props":{"name":"kang","age":42,"skills":["swift","js","ts","kotlin",1]}},"f":["array","test"]} | |
{"title":"abc"} | |
{"name":"kim"} | |
{"a":3} | |
*/ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
수정하였습니다.