From d7ccd26366bcc78fb2d82d05823c8ccbc164dfb4 Mon Sep 17 00:00:00 2001 From: "Arkady.Bazhanov" Date: Wed, 6 Mar 2024 16:08:32 +0100 Subject: [PATCH] Fix #425: Similar classes get incorrectly deduplicated --- .../wu/seal/jsontokotlin/utils/Extensions.kt | 12 ++-- .../jsontokotlin/regression/Issue425Test.kt | 66 +++++++++++++++++++ 2 files changed, 72 insertions(+), 6 deletions(-) create mode 100644 src/test/kotlin/wu/seal/jsontokotlin/regression/Issue425Test.kt diff --git a/src/main/kotlin/wu/seal/jsontokotlin/utils/Extensions.kt b/src/main/kotlin/wu/seal/jsontokotlin/utils/Extensions.kt index 0255a8bb..97e9c077 100755 --- a/src/main/kotlin/wu/seal/jsontokotlin/utils/Extensions.kt +++ b/src/main/kotlin/wu/seal/jsontokotlin/utils/Extensions.kt @@ -290,16 +290,16 @@ private fun List.distinctByPropertiesAndSimilarClassNameOneTime(): } return replaceReferencedClasses(rule) } - //If class name the same with XXXX append or only diff with number, then treat them as the same class to do distinct - val distinctClassesWhenClassNameSimilar = distinctBy { - it.codeWithoutXAndNumberClassName() - } + //If class name the same with XXXX append or only diff with number, then group them in the same entry //obtain the class to replace other ref class, if the replace times is less then 2, then it means that no need to replace val targetClass = groupBy { it.codeWithoutXAndNumberClassName() }.maxByOrNull { it.value.size } ?.takeIf { it.value.size > 1 }?.value?.first() ?: return this - return distinctClassesWhenClassNameSimilar.map { - if (targetClass == it) return@map it + return mapNotNull { + if (targetClass == it) return@mapNotNull it + if (it.codeWithoutXAndNumberClassName() == targetClass.codeWithoutXAndNumberClassName()) { + return@mapNotNull null // removing the classes that we are replacing + } it.replaceClassRefRecursive { if (it.codeWithoutXAndNumberClassName() == targetClass.codeWithoutXAndNumberClassName()) { targetClass diff --git a/src/test/kotlin/wu/seal/jsontokotlin/regression/Issue425Test.kt b/src/test/kotlin/wu/seal/jsontokotlin/regression/Issue425Test.kt new file mode 100644 index 00000000..1f6e0b19 --- /dev/null +++ b/src/test/kotlin/wu/seal/jsontokotlin/regression/Issue425Test.kt @@ -0,0 +1,66 @@ +package wu.seal.jsontokotlin.regression + +import com.winterbe.expekt.should +import org.junit.Test +import wu.seal.jsontokotlin.generateKotlinClassCode +import wu.seal.jsontokotlin.model.DefaultValueStrategy +import wu.seal.jsontokotlin.model.TargetJsonConverter +import wu.seal.jsontokotlin.test.TestConfig +import wu.seal.jsontokotlin.utils.BaseTest + +class Issue425Test : BaseTest() { + @Test + fun testIssue425() { + val json = """ + { + "firstTeam": { + "hometown": { + "name": "Town 1" + }, + "stats": { + "rating": 10 + } + }, + "secondTeam": { + "hometown": { + "name": "Town 2" + }, + "stats": { + "rating": 20 + } + } + } + """.trimIndent() + val expected = """ + data class Match( + val firstTeam: FirstTeam, + val secondTeam: SecondTeam + ) + + data class FirstTeam( + val hometown: Hometown, + val stats: Stats + ) + + data class SecondTeam( + val hometown: Hometown, + val stats: Stats + ) + + data class Hometown( + val name: String + ) + + data class Stats( + val rating: Int + ) + """.trimIndent() + TestConfig.apply { + isCommentOff = true + targetJsonConvertLib = TargetJsonConverter.None + defaultValueStrategy = DefaultValueStrategy.None + isNestedClassModel = false + } + json.generateKotlinClassCode("Match").should.equal(expected) + } +}