Skip to content

Commit 53832ca

Browse files
authored
Merge pull request #78 from wuseal/fixUnsupportException
Fix unsupport exception
2 parents c6616f7 + 42c0bdf commit 53832ca

File tree

9 files changed

+239
-59
lines changed

9 files changed

+239
-59
lines changed

build.gradle

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
buildscript {
2-
ext.kotlin_version = '1.2.31'
2+
ext.kotlin_version = '1.2.51'
33

44
repositories {
55
mavenLocal()

src/main/kotlin/wu/seal/jsontokotlin/KotlinCodeMaker.kt

Lines changed: 54 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
package wu.seal.jsontokotlin
22

3+
import com.google.gson.Gson
34
import com.google.gson.JsonElement
45
import com.google.gson.JsonObject
6+
import com.sun.org.apache.regexp.internal.RE
57
import wu.seal.jsontokotlin.codeelements.KClassAnnotation
68
import wu.seal.jsontokotlin.codeelements.KProperty
79
import wu.seal.jsontokotlin.utils.*
@@ -16,16 +18,20 @@ class KotlinCodeMaker {
1618
private var className: String? = null
1719
private var inputElement: JsonElement? = null
1820

21+
private var originElement:JsonElement
22+
1923
private val indent = getIndent()
2024

2125
private val toBeAppend = HashSet<String>()
2226

2327
constructor(className: String, inputText: String) {
28+
originElement = Gson().fromJson<JsonElement>(inputText,JsonElement::class.java)
2429
this.inputElement = TargetJsonElement(inputText).getTargetJsonElementForGeneratingCode()
2530
this.className = className
2631
}
2732

2833
constructor(className: String, jsonElement: JsonElement) {
34+
originElement = jsonElement
2935
this.inputElement = TargetJsonElement(jsonElement).getTargetJsonElementForGeneratingCode()
3036
this.className = className
3137
}
@@ -35,12 +41,10 @@ class KotlinCodeMaker {
3541
stringBuilder.append("\n")
3642

3743
val jsonElement = inputElement
38-
if (jsonElement!!.isJsonObject) {
39-
appClassName(stringBuilder)
40-
appendCodeMember(stringBuilder, jsonElement.asJsonObject)
41-
} else {
42-
throw IllegalArgumentException("UnSupport")
43-
}
44+
checkIsNotEmptyObjectJSONElement(jsonElement)
45+
46+
appendClassName(stringBuilder)
47+
appendCodeMember(stringBuilder, jsonElement?.asJsonObject!!)
4448

4549
stringBuilder.append(")")
4650
if (toBeAppend.isNotEmpty()) {
@@ -50,6 +54,35 @@ class KotlinCodeMaker {
5054
return stringBuilder.toString()
5155
}
5256

57+
//the fucking code
58+
private fun checkIsNotEmptyObjectJSONElement(jsonElement: JsonElement?) {
59+
if (jsonElement!!.isJsonObject) {
60+
if (jsonElement.asJsonObject.entrySet().isEmpty() && originElement.isJsonArray) {
61+
//when [[[{}]]]
62+
if (originElement.asJsonArray.onlyHasOneElementRecursive()) {
63+
val unSupportJsonException = UnSupportJsonException("Unsupported Json String")
64+
val adviceType = getArrayType("Any", originElement.asJsonArray).replace(Regex("Int|Float|String|Boolean"), "Any")
65+
unSupportJsonException.advice = """No need converting, just use $adviceType is enough for your json string"""
66+
throw unSupportJsonException
67+
} else {
68+
//when [1,"a"]
69+
val unSupportJsonException = UnSupportJsonException("Unsupported Json String")
70+
unSupportJsonException.advice = """No need converting, just use List<Any> is enough for your json string"""
71+
throw unSupportJsonException
72+
}
73+
}
74+
} else {
75+
/**
76+
* in this condition the only result it that we just give the json a List<Any> type is enough, No need to
77+
* do any convert to make class type
78+
*/
79+
val unSupportJsonException = UnSupportJsonException("Unsupported Json String")
80+
val adviceType = getArrayType("Any", originElement.asJsonArray).replace("AnyX", "Any")
81+
unSupportJsonException.advice = """No need converting, just use $adviceType is enough for your json string"""
82+
throw unSupportJsonException
83+
}
84+
}
85+
5386
private fun appendSubClassCode(stringBuilder: StringBuilder) {
5487
if (ConfigManager.isInnerClassModel) {
5588
appendInnerClassModelSubClassCode(stringBuilder)
@@ -77,7 +110,7 @@ class KotlinCodeMaker {
77110
}
78111
}
79112

80-
private fun appClassName(stringBuilder: StringBuilder) {
113+
private fun appendClassName(stringBuilder: StringBuilder) {
81114
val classAnnotation = KClassAnnotation.getClassAnnotation(className.toString())
82115
stringBuilder.append(classAnnotation)
83116
if (classAnnotation.isNotBlank()) stringBuilder.append("\n")
@@ -111,14 +144,12 @@ class KotlinCodeMaker {
111144
if (ConfigManager.enableMapType && maybeJsonObjectBeMapType(jsonElementValue.asJsonObject)) {
112145
val mapKeyType = getMapKeyTypeConvertFromJsonObject(jsonElementValue.asJsonObject)
113146
val mapValueType = getMapValueTypeConvertFromJsonObject(jsonElementValue.asJsonObject)
114-
if (mapValueType == MAP_DEFAULT_OBJECT_VALUE_TYPE
115-
|| mapValueType.contains(MAP_DEFAULT_ARRAY_ITEM_VALUE_TYPE)
116-
) {
147+
if (mapValueIsObjectType(mapValueType)) {
117148
toBeAppend.add(
118-
KotlinCodeMaker(
119-
getChildType(mapValueType),
120-
jsonElementValue.asJsonObject.entrySet().first().value
121-
).makeKotlinData()
149+
KotlinCodeMaker(
150+
getChildType(mapValueType),
151+
jsonElementValue.asJsonObject.entrySet().first().value
152+
).makeKotlinData()
122153
)
123154
}
124155
val mapType = "Map<$mapKeyType,$mapValueType>"
@@ -136,13 +167,16 @@ class KotlinCodeMaker {
136167
}
137168
}
138169

170+
private fun mapValueIsObjectType(mapValueType: String) = (mapValueType == MAP_DEFAULT_OBJECT_VALUE_TYPE
171+
|| mapValueType.contains(MAP_DEFAULT_ARRAY_ITEM_VALUE_TYPE))
172+
139173

140174
private fun addProperty(
141-
stringBuilder: StringBuilder,
142-
property: String,
143-
type: String,
144-
value: String?,
145-
isLast: Boolean = false
175+
stringBuilder: StringBuilder,
176+
property: String,
177+
type: String,
178+
value: String?,
179+
isLast: Boolean = false
146180
) {
147181
var innerValue = value
148182
if (innerValue == null) {
@@ -158,7 +192,7 @@ class KotlinCodeMaker {
158192
val propertyComment = p.getPropertyComment()
159193
if (!ConfigManager.isCommentOff && propertyComment.isNotBlank())
160194
stringBuilder.append(" // ")
161-
.append(getCommentCode(propertyComment))
195+
.append(getCommentCode(propertyComment))
162196
stringBuilder.append("\n")
163197
}
164198

src/main/kotlin/wu/seal/jsontokotlin/MakeKotlinClassAction.kt

Lines changed: 35 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ class MakeKotlinClassAction : AnAction("MakeKotlinClass") {
4242
*/
4343
var tempClassName = ""
4444
val couldGetAndReuseClassNameInCurrentEditFileForInsertCode =
45-
couldGetAndReuseClassNameInCurrentEditFileForInsertCode(editorText)
45+
couldGetAndReuseClassNameInCurrentEditFileForInsertCode(editorText)
4646

4747
if (couldGetAndReuseClassNameInCurrentEditFileForInsertCode) {
4848
/**
@@ -54,9 +54,9 @@ class MakeKotlinClassAction : AnAction("MakeKotlinClass") {
5454
inputDialog.show()
5555
val className = inputDialog.getClassName()
5656
val inputString = inputDialog.inputString
57-
val json = if (inputString?.startsWith("http") == true) {
57+
val json = if (inputString?.startsWith("http") == true) {
5858
URL(inputString).readText()
59-
} else inputString
59+
} else inputString
6060
if (json == null || json.isEmpty()) {
6161
return
6262
}
@@ -75,16 +75,21 @@ class MakeKotlinClassAction : AnAction("MakeKotlinClass") {
7575
}
7676

7777

78+
} catch (e: UnSupportJsonException) {
79+
val advice = e.advice
80+
Messages.showInfoMessage(dealWithHtmlConvert(advice), "Tip")
7881
} catch (e: Throwable) {
7982
dealWithException(jsonString, e)
8083
throw e
8184
}
8285
}
8386

87+
private fun dealWithHtmlConvert(advice: String) = advice.replace("<", "&lt;").replace(">", "&gt;")
88+
8489
private fun reuseClassName(
85-
couldGetAndReuseClassNameInCurrentEditFileForInserCode: Boolean,
86-
className: String,
87-
tempClassName: String
90+
couldGetAndReuseClassNameInCurrentEditFileForInserCode: Boolean,
91+
className: String,
92+
tempClassName: String
8893
) = couldGetAndReuseClassNameInCurrentEditFileForInserCode && className == tempClassName
8994

9095
private fun couldNotInsertCode(editor: Editor?): Boolean {
@@ -108,11 +113,11 @@ class MakeKotlinClassAction : AnAction("MakeKotlinClass") {
108113
}
109114

110115
private fun insertKotlinCode(
111-
project: Project?,
112-
document: Document,
113-
className: String,
114-
jsonString: String,
115-
caret: Caret?
116+
project: Project?,
117+
document: Document,
118+
className: String,
119+
jsonString: String,
120+
caret: Caret?
116121
): Boolean {
117122
ImportClassWriter.insertImportClassCode(project, document)
118123

@@ -125,6 +130,8 @@ class MakeKotlinClassAction : AnAction("MakeKotlinClass") {
125130
return false
126131
}
127132

133+
val generateClassesString = codeMaker.makeKotlinDataClassCode()
134+
128135
executeCouldRollBackAction(project) {
129136
var offset: Int
130137

@@ -138,8 +145,8 @@ class MakeKotlinClassAction : AnAction("MakeKotlinClass") {
138145
offset = document.textLength
139146
}
140147
document.insertString(
141-
Math.max(offset, 0),
142-
ClassCodeFilter.removeDuplicateClassCode(codeMaker.makeKotlinDataClassCode())
148+
Math.max(offset, 0),
149+
ClassCodeFilter.removeDuplicateClassCode(generateClassesString)
143150
)
144151
}
145152
return true
@@ -153,12 +160,12 @@ class MakeKotlinClassAction : AnAction("MakeKotlinClass") {
153160
fun getCleanText(editorText: String): String {
154161
val tempCleanText = editorText.substringBeforeLast("class")
155162
val cleanText =
156-
if (tempCleanText.trim().endsWith("data")) tempCleanText.trim().removeSuffix("data") else tempCleanText
163+
if (tempCleanText.trim().endsWith("data")) tempCleanText.trim().removeSuffix("data") else tempCleanText
157164
return cleanText
158165
}
159166

160167
fun getCurrentEditFileTemClassName(editorText: String) = editorText.substringAfterLast("class")
161-
.substringBefore("(").substringBefore("{").trim()
168+
.substringBefore("(").substringBefore("{").trim()
162169

163170
/**
164171
* whether we could reuse current class name declared in the edit file for inserting data class code
@@ -169,20 +176,20 @@ class MakeKotlinClassAction : AnAction("MakeKotlinClass") {
169176
var couldGetAndReuseClassNameInCurrentEditFileForInsertCode = false
170177
val removeDocComment = editorText.replace(Regex("/\\*\\*(.|\n)*\\*/", RegexOption.MULTILINE), "")
171178
val removeDocCommentAndPackageDeclareText = removeDocComment
172-
.replace(Regex("^(?:\\s*package |\\s*import ).*$", RegexOption.MULTILINE), "")
179+
.replace(Regex("^(?:\\s*package |\\s*import ).*$", RegexOption.MULTILINE), "")
173180
if ((removeDocCommentAndPackageDeclareText.indexOf("class") == removeDocCommentAndPackageDeclareText.lastIndexOf(
174-
"class"
175-
)
176-
&& removeDocCommentAndPackageDeclareText.indexOf("class") != -1
177-
&& removeDocCommentAndPackageDeclareText.substringAfter("class").contains("(").not()
178-
&& removeDocCommentAndPackageDeclareText.substringAfter("class").contains(":").not()
179-
&& removeDocCommentAndPackageDeclareText.substringAfter("class").contains("=").not())
180-
|| (removeDocCommentAndPackageDeclareText.indexOf("class") == removeDocCommentAndPackageDeclareText.lastIndexOf(
181-
"class"
182-
)
183-
&& removeDocCommentAndPackageDeclareText.indexOf("class") != -1
184-
&& removeDocCommentAndPackageDeclareText.substringAfter("class").substringAfter("(")
185-
.replace(Regex("\\s"), "").let { it.equals(")") || it.equals("){}") })
181+
"class"
182+
)
183+
&& removeDocCommentAndPackageDeclareText.indexOf("class") != -1
184+
&& removeDocCommentAndPackageDeclareText.substringAfter("class").contains("(").not()
185+
&& removeDocCommentAndPackageDeclareText.substringAfter("class").contains(":").not()
186+
&& removeDocCommentAndPackageDeclareText.substringAfter("class").contains("=").not())
187+
|| (removeDocCommentAndPackageDeclareText.indexOf("class") == removeDocCommentAndPackageDeclareText.lastIndexOf(
188+
"class"
189+
)
190+
&& removeDocCommentAndPackageDeclareText.indexOf("class") != -1
191+
&& removeDocCommentAndPackageDeclareText.substringAfter("class").substringAfter("(")
192+
.replace(Regex("\\s"), "").let { it.equals(")") || it.equals("){}") })
186193
) {
187194
couldGetAndReuseClassNameInCurrentEditFileForInsertCode = true
188195
}

src/main/kotlin/wu/seal/jsontokotlin/TargetJsonElement.kt

Lines changed: 65 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,13 @@
11
package wu.seal.jsontokotlin
22

33
import com.google.gson.*
4+
import wu.seal.jsontokotlin.utils.onlyHasOneElementRecursive
45
import java.util.*
56

6-
7+
/**
8+
* This class aim at filtering out the expected Json Element to be convert from Json array
9+
*
10+
*/
711
class TargetJsonElement : ITargetJsonElement {
812
private val jsonElement: JsonElement
913

@@ -17,16 +21,68 @@ class TargetJsonElement : ITargetJsonElement {
1721

1822
override fun getTargetJsonElementForGeneratingCode(): JsonElement {
1923
if (this.jsonElement.isJsonArray) {
20-
val jsonElementNotArray = getArrayChildElement(this.jsonElement.asJsonArray)
21-
if (jsonElementNotArray.isJsonObject) {
22-
return jsonElementNotArray
24+
if (jsonElement.asJsonArray.size() == 0) {
25+
return gson.toJsonTree(Any())
26+
} else if (allElementAreObject(jsonElement.asJsonArray)) {
27+
val jsonElementNotArray = getArrayChildElement(this.jsonElement.asJsonArray)
28+
if (jsonElementNotArray.isJsonObject) {
29+
return jsonElementNotArray
30+
} else {
31+
throw IllegalStateException("Unbelievable! should not throw out this exception")
32+
}
33+
} else if(jsonElement.asJsonArray.onlyHasOneElementRecursive()){
34+
return getArrayChildElement(this.jsonElement.asJsonArray)
35+
} else if (allElementAreSamePrimitiveType(jsonElement.asJsonArray)) {
36+
return jsonElement.asJsonArray[0]
37+
} else {
38+
return gson.toJsonTree(Any())
2339
}
2440
} else if (this.jsonElement.isJsonObject) {
2541
return this.jsonElement
42+
} else if (this.jsonElement.isJsonPrimitive) {
43+
return this.jsonElement
44+
} else {
45+
return this.jsonElement
46+
}
47+
}
48+
49+
50+
private fun allElementAreObject(jsonArray: JsonArray): Boolean {
51+
var allElementAreObject = true
52+
jsonArray.forEach {
53+
if (it.isJsonObject.not()) {
54+
allElementAreObject = false
55+
return@forEach
56+
}
57+
}
58+
return allElementAreObject
59+
}
60+
61+
private fun allElementAreSamePrimitiveType(jsonArray: JsonArray): Boolean {
62+
var allElementAreSamePrimitiveType = true
63+
jsonArray.forEach {
64+
if (it.isJsonPrimitive.not()) {
65+
allElementAreSamePrimitiveType = false
66+
return@forEach
67+
}
68+
if (theSamePrimitiveType(jsonArray[0].asJsonPrimitive, it.asJsonPrimitive).not()) {
69+
allElementAreSamePrimitiveType = false
70+
return@forEach
71+
}
2672
}
27-
throw IllegalFormatFlagsException("Unsupported Json String")
73+
return allElementAreSamePrimitiveType
2874
}
2975

76+
private fun theSamePrimitiveType(first: JsonPrimitive, second: JsonPrimitive): Boolean {
77+
78+
val sameBoolean = first.isBoolean && second.isBoolean
79+
80+
val sameNumber = first.isNumber && second.isNumber
81+
82+
val sameString = first.isString && second.isString
83+
84+
return sameBoolean || sameNumber || sameString
85+
}
3086

3187
private fun getArrayChildElement(jsonArray: JsonArray): JsonElement {
3288
if (jsonArray.size() >= 1) {
@@ -43,6 +99,8 @@ class TargetJsonElement : ITargetJsonElement {
4399
/**
44100
* get an element from the element array , And the result element should contains all the json field in every
45101
* element of the array
102+
*
103+
* the input argument jsonArray should only contains jsonObject or only contains one element Recursive like [[["element"]]]
46104
*/
47105
fun getFullFieldElementFromArrayElement(jsonArray: JsonArray): JsonElement {
48106

@@ -66,6 +124,8 @@ class TargetJsonElement : ITargetJsonElement {
66124

67125
return gson.fromJson(gson.toJson(map), JsonElement::class.java)
68126
}
127+
128+
69129
}
70130

71131
}

0 commit comments

Comments
 (0)