1 /* <lambda>null2 * Copyright 2017-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. 3 */ 4 5 @file:Suppress("ReplaceArrayOfWithLiteral") // https://youtrack.jetbrains.com/issue/KT-22578 6 7 package kotlinx.serialization.features 8 9 import kotlinx.serialization.* 10 import kotlinx.serialization.json.* 11 import kotlinx.serialization.test.* 12 import kotlin.test.* 13 14 class JsonNamesTest : JsonTestBase() { 15 16 @Serializable 17 data class WithNames(@JsonNames("foo", "_foo") val data: String) 18 19 @Serializable 20 enum class AlternateEnumNames { 21 @JsonNames("someValue", "some_value") 22 VALUE_A, 23 VALUE_B 24 } 25 26 @Serializable 27 data class WithEnumNames( 28 val enumList: List<AlternateEnumNames>, 29 val checkCoercion: AlternateEnumNames = AlternateEnumNames.VALUE_B 30 ) 31 32 @Serializable 33 data class CollisionWithAlternate( 34 @JsonNames("_foo") val data: String, 35 @JsonNames("_foo") val foo: String 36 ) 37 38 private val inputString1 = """{"foo":"foo"}""" 39 private val inputString2 = """{"_foo":"foo"}""" 40 41 private fun parameterizedCoercingTest(test: (json: Json, streaming: JsonTestingMode, msg: String) -> Unit) { 42 for (coercing in listOf(true, false)) { 43 val json = Json { 44 coerceInputValues = coercing 45 useAlternativeNames = true 46 } 47 parametrizedTest { streaming -> 48 test( 49 json, streaming, 50 "Failed test with coercing=$coercing and streaming=$streaming" 51 ) 52 } 53 } 54 } 55 56 @Test 57 fun testEnumSupportsAlternativeNames() { 58 val input = """{"enumList":["VALUE_A", "someValue", "some_value", "VALUE_B"], "checkCoercion":"someValue"}""" 59 val expected = WithEnumNames( 60 listOf( 61 AlternateEnumNames.VALUE_A, 62 AlternateEnumNames.VALUE_A, 63 AlternateEnumNames.VALUE_A, 64 AlternateEnumNames.VALUE_B 65 ), AlternateEnumNames.VALUE_A 66 ) 67 parameterizedCoercingTest { json, streaming, msg -> 68 assertEquals(expected, json.decodeFromString(input, streaming), msg) 69 } 70 } 71 72 @Test 73 fun topLevelEnumSupportAlternativeNames() { 74 parameterizedCoercingTest { json, streaming, msg -> 75 assertEquals(AlternateEnumNames.VALUE_A, json.decodeFromString("\"someValue\"", streaming), msg) 76 } 77 } 78 79 @Test 80 fun testParsesAllAlternativeNames() { 81 for (input in listOf(inputString1, inputString2)) { 82 parameterizedCoercingTest { json, streaming, _ -> 83 val data = json.decodeFromString(WithNames.serializer(), input, jsonTestingMode = streaming) 84 assertEquals("foo", data.data, "Failed to parse input '$input' with streaming=$streaming") 85 } 86 } 87 } 88 89 @Test 90 fun testThrowsAnErrorOnDuplicateNames() { 91 val serializer = CollisionWithAlternate.serializer() 92 parameterizedCoercingTest { json, streaming, _ -> 93 assertFailsWithMessage<SerializationException>( 94 """The suggested name '_foo' for property foo is already one of the names for property data""", 95 "Class ${serializer.descriptor.serialName} did not fail with streaming=$streaming" 96 ) { 97 json.decodeFromString( 98 serializer, inputString2, 99 jsonTestingMode = streaming 100 ) 101 } 102 } 103 } 104 } 105