feature/dynamic_resourceDoc: add typeNamePrefix when generate case class with JValue

This commit is contained in:
shuang 2021-02-18 17:28:18 +08:00
parent 506e0bc0f1
commit 92cd1ffdcd
2 changed files with 48 additions and 33 deletions

View File

@ -725,7 +725,7 @@ object JsonUtils {
}
}
private def getNestedJObjects(jObject: JObject): List[String] = {
private def getNestedJObjects(jObject: JObject, typeNamePrefix: String): List[String] = {
val nestedObjects = collectField(jObject) {
case (JField(_, _: JObject), _) => true
case (JField(_, JArray((_: JObject) :: _)), _) => true
@ -741,18 +741,18 @@ object JsonUtils {
val subTypes: List[String] = nestedObjects collect {
case (JField(name, v: JObject), path) =>
jObjectToCaseClass(v, name, getParentFiledName(path))
jObjectToCaseClass(v, typeNamePrefix, name, getParentFiledName(path))
case (JField(name, JArray((v: JObject) :: _)), path) =>
jObjectToCaseClass(v, name, getParentFiledName(path))
jObjectToCaseClass(v, typeNamePrefix, name, getParentFiledName(path))
case (JField(name, JArray(JArray((v: JObject) :: _) :: _)), path) =>
jObjectToCaseClass(v, name, getParentFiledName(path))
jObjectToCaseClass(v, typeNamePrefix, name, getParentFiledName(path))
case (JField(name, JArray(JArray(JArray((v: JObject) :: _) :: _) :: _)), path) =>
jObjectToCaseClass(v, name, getParentFiledName(path))
jObjectToCaseClass(v, typeNamePrefix, name, getParentFiledName(path))
case (JField(name, JArray(JArray(JArray(JArray((v: JObject) :: _) :: _) :: _) :: _)), path) =>
jObjectToCaseClass(v, name, getParentFiledName(path))
jObjectToCaseClass(v, typeNamePrefix, name, getParentFiledName(path))
case (JField(name, JArray(JArray(JArray(JArray(JArray((v: JObject) :: _) :: _) :: _) :: _) :: _)), path) =>
jObjectToCaseClass(v, name, getParentFiledName(path))
case (JField(name, JArray(JArray(JArray(JArray(JArray(JArray(_ :: _) :: _) :: _) :: _) :: _) :: _)), path) =>
jObjectToCaseClass(v, typeNamePrefix, name, getParentFiledName(path))
case (JField(_, JArray(JArray(JArray(JArray(JArray(JArray(_ :: _) :: _) :: _) :: _) :: _) :: _)), path) =>
throw new IllegalArgumentException(s"Json field $path have too much nested level, max nested level be supported is 5.")
} toList
@ -764,16 +764,16 @@ object JsonUtils {
* @param jvalue
* @return case class string
*/
def toCaseClasses(jvalue: JValue): String = {
def toCaseClasses(jvalue: JValue, typeNamePrefix: String = ""): String = {
validateJArray(jvalue)
jvalue match {
case _: JBool => "type RootJsonClass = Boolean"
case _: JString => "type RootJsonClass = String"
case _: JDouble => "type RootJsonClass = Double"
case _: JInt => "type RootJsonClass = Long"
case _: JBool => s"type ${typeNamePrefix}RootJsonClass = Boolean"
case _: JString => s"type ${typeNamePrefix}RootJsonClass = String"
case _: JDouble => s"type ${typeNamePrefix}RootJsonClass = Double"
case _: JInt => s"type ${typeNamePrefix}RootJsonClass = Long"
case jObject: JObject =>
validateJArray(jObject)
val allDefinitions = getNestedJObjects(jObject) :+ jObjectToCaseClass(jObject)
val allDefinitions = getNestedJObjects(jObject, typeNamePrefix) :+ jObjectToCaseClass(jObject, typeNamePrefix)
allDefinitions mkString "\n"
case jArray: JArray =>
@ -785,9 +785,9 @@ object JsonUtils {
case _: JDouble => "List[Double]"
case _: JInt => "List[Long]"
case v: JObject =>
val itemsType = jObjectToCaseClass(v, "RootItem")
val itemsType = jObjectToCaseClass(v, typeNamePrefix, "RootItem")
s"""$itemsType
|List[RootItemJsonClass]
|List[${typeNamePrefix}RootItemJsonClass]
|""".stripMargin
case v: JArray =>
val nestedItmType = buildArrayType(v)
@ -802,7 +802,7 @@ object JsonUtils {
nestedItmType.replaceAll("(^|.*\\s+)(.+)\\s*$", "$1List[$2]")
}
// add type alias for last row
buildArrayType(jArray).replaceAll("(^|.*\\s+)(.+)\\s*$", "$1 type RootJsonClass = $2")
buildArrayType(jArray).replaceAll("(^|.*\\s+)(.+)\\s*$", s"$$1 type ${typeNamePrefix}RootJsonClass = $$2")
case null | JNull | JNothing => throw new IllegalArgumentException(s"null value json can't generate case class")
}
@ -810,7 +810,7 @@ object JsonUtils {
}
private def jObjectToCaseClass(jObject: JObject, fieldName: String = "", parentFieldName: String = ""): String = {
private def jObjectToCaseClass(jObject: JObject, typeNamePrefix: String, fieldName: String = "", parentFieldName: String = ""): String = {
val JObject(fields) = jObject
val optionalFields = (jObject \ optionalFieldName) match {
case JArray(arr) if arr.forall(_.isInstanceOf[JString]) =>
@ -819,7 +819,7 @@ object JsonUtils {
case _ => throw new IllegalArgumentException(s"Filed $optionalFieldName of $fieldName should be an array of String")
}
def toCaseClassName(name: String) = s"${fieldName.capitalize}${name.capitalize}JsonClass"
def toCaseClassName(name: String) = s"$typeNamePrefix${fieldName.capitalize}${name.capitalize}JsonClass"
val currentCaseClass: String = fields collect {
case JField(name, v) if isBasicType(v) =>
@ -850,7 +850,7 @@ object JsonUtils {
val escapedFieldsName = reservedToEscaped.getOrElse(name, name)
s"$escapedFieldsName: $fieldType"
} mkString(s"case class ${parentFieldName.capitalize}${if(fieldName.isEmpty) "Root" else fieldName.capitalize}JsonClass(", ", ", ")")
} mkString(s"case class $typeNamePrefix${parentFieldName.capitalize}${if(fieldName.isEmpty) "Root" else fieldName.capitalize}JsonClass(", ", ", ")")
currentCaseClass
}

View File

@ -42,7 +42,7 @@ class JsonUtilsTest extends FlatSpec with Matchers {
names should not contain ("nestField1")
}
def toCaseClass(str: String): String = JsonUtils.toCaseClasses(json.parse(str))
def toCaseClass(str: String, typeNamePrefix: String = ""): String = JsonUtils.toCaseClasses(json.parse(str), typeNamePrefix)
"object json String" should "generate correct case class" taggedAs FunctionsTag in {
@ -66,15 +66,27 @@ class JsonUtilsTest extends FlatSpec with Matchers {
|}
|""".stripMargin
}
val expectedCaseClass =
"""case class AddressStreetJsonClass(road: String, number: Long)
|case class AddressJsonClass(name: String, code: Long, street: AddressStreetJsonClass)
|case class StreetJsonClass(name: String, width: Double)
|case class RootJsonClass(name: String, age: Option[java.lang.Long], isMarried: Boolean, weight: Option[java.lang.Double], `class`: String, `def`: Long, email: List[String], address: Option[List[AddressJsonClass]], street: StreetJsonClass)""".stripMargin
{
val expectedCaseClass =
"""case class AddressStreetJsonClass(road: String, number: Long)
|case class AddressJsonClass(name: String, code: Long, street: AddressStreetJsonClass)
|case class StreetJsonClass(name: String, width: Double)
|case class RootJsonClass(name: String, age: Option[java.lang.Long], isMarried: Boolean, weight: Option[java.lang.Double], `class`: String, `def`: Long, email: List[String], address: Option[List[AddressJsonClass]], street: StreetJsonClass)""".stripMargin
val generatedCaseClass = toCaseClass(zson)
val generatedCaseClass = toCaseClass(zson)
generatedCaseClass should be (expectedCaseClass)
generatedCaseClass should be(expectedCaseClass)
}
{// test type name prefix
val expectedCaseClass =
"""case class RequestAddressStreetJsonClass(road: String, number: Long)
|case class RequestAddressJsonClass(name: String, code: Long, street: RequestAddressStreetJsonClass)
|case class RequestStreetJsonClass(name: String, width: Double)
|case class RequestRootJsonClass(name: String, age: Option[java.lang.Long], isMarried: Boolean, weight: Option[java.lang.Double], `class`: String, `def`: Long, email: List[String], address: Option[List[RequestAddressJsonClass]], street: RequestStreetJsonClass)""".stripMargin
val generatedCaseClass = toCaseClass(zson, "Request")
generatedCaseClass should be(expectedCaseClass)
}
}
"List json" should "generate correct case class" taggedAs FunctionsTag in {
@ -82,9 +94,8 @@ class JsonUtilsTest extends FlatSpec with Matchers {
val listIntJson = """[1,2,3]"""
val expectedCaseClass = """ type RootJsonClass = List[Long]"""
val generatedCaseClass = toCaseClass(listIntJson)
generatedCaseClass should be(expectedCaseClass)
toCaseClass(listIntJson) should be(""" type RootJsonClass = List[Long]""")
toCaseClass(listIntJson, "Response") should be(""" type ResponseRootJsonClass = List[Long]""")
}
{
val listObjectJson =
@ -101,11 +112,15 @@ class JsonUtilsTest extends FlatSpec with Matchers {
val expectedCaseClass = """case class RootItemJsonClass(name: String, weight: Double)
| type RootJsonClass = List[RootItemJsonClass]""".stripMargin
val generatedCaseClass = toCaseClass(listObjectJson)
val expectedRequestCaseClass = """case class RequestRootItemJsonClass(name: String, weight: Double)
| type RequestRootJsonClass = List[RequestRootItemJsonClass]""".stripMargin
generatedCaseClass should be(expectedCaseClass)
toCaseClass(listObjectJson) should be(expectedCaseClass)
toCaseClass(listObjectJson, "Request") should be(expectedRequestCaseClass)
}
}
"List json have different type items" should "throw exception" taggedAs FunctionsTag in {
val listJson = """["abc",2,3]"""