根据给定的json字符串和案例类类型将json字符串转换为案例类对象

时间:2020-04-01 20:00:49

标签: json scala jackson gson case-class

要求是在给定jsonString和case类的类型的情况下,将scala中的json字符串转换为case类对象。

我尝试了Gson和jackson库,但无法解决给定的要求。

package eg.json

import com.fasterxml.jackson.databind.ObjectMapper
import com.google.gson.Gson
import com.typesafe.scalalogging.LazyLogging

case class Person(name : String, age : Int)

case class Address(street : String, buildingNumber : Int, zipCode : Int)

case class Rent(amount : Double, month : String)

//there are many other case classes

object JsonToObject extends LazyLogging{

  import logger._

  def toJsonString(ref : Any) : String = {
    val gson = new Gson()
    val jsonString = gson.toJson(ref)
    jsonString
  }

  def main(args: Array[String]): Unit = {
    val person = Person("John", 35)
    val jsonString = toJsonString(person)

    //here requirement is to convert json string to case class instance, provided the type of case class instance

    val gsonObj = toInstanceUsingGson( jsonString, Person.getClass )
    debug(s"main : object deserialized using gson : $gsonObj")

    val jacksonObj = toInstanceUsingJackson( jsonString, Person.getClass )
    debug(s"main : object deserialized using gson : $jacksonObj")

  }

  def toInstanceUsingGson[T](jsonString : String, caseClassType : Class[T]) : T = {

    val gson = new Gson()
    val ref = gson.fromJson(jsonString, caseClassType)
    ref
  }

  def toInstanceUsingJackson[T](jsonString : String, caseClassType : Class[T]) : T = {

    val mapper = new ObjectMapper()
    val ref = mapper.readValue(jsonString, caseClassType)
    ref
  }
}

以上代码的执行输出为:-

01:32:52.369 [main] DEBUG eg.json.JsonToObject$ - main : object deserialized using gson : Person
Exception in thread "main" com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException: Unrecognized field "name" (class eg.json.Person$), not marked as ignorable (0 known properties: ])
 at [Source: (String)"{"name":"John","age":35}"; line: 1, column: 10] (through reference chain: eg.json.Person$["name"])
    at com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException.from(UnrecognizedPropertyException.java:60)
    at com.fasterxml.jackson.databind.DeserializationContext.handleUnknownProperty(DeserializationContext.java:822)
    at com.fasterxml.jackson.databind.deser.std.StdDeserializer.handleUnknownProperty(StdDeserializer.java:1152)
    at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.handleUnknownProperty(BeanDeserializerBase.java:1589)
    at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.handleUnknownVanilla(BeanDeserializerBase.java:1567)
    at com.fasterxml.jackson.databind.deser.BeanDeserializer.vanillaDeserialize(BeanDeserializer.java:294)
    at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:151)
    at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:4013)
    at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3004)
    at eg.json.JsonToObject$.toInstanceUsingJackson(JsonToObject.scala:49)
    at eg.json.JsonToObject$.main(JsonToObject.scala:34)
    at eg.json.JsonToObject.main(JsonToObject.scala)

请提出如何使用gson或jackson实现此目的,或提出带有示例示例的其他库。

上面的简化问题在github上:-

https://github.com/moglideveloper/JsonToScalaObject

2 个答案:

答案 0 :(得分:0)

尝试使用Cats的circe。

  • 将圈子添加到您的项目(https://circe.github.io/circe/-快速入门)。
  • 创建一个案例类,以表示要从json构建的内容。
  • 声明解码器

https://circe.github.io/circe/codecs/semiauto-derivation.html https://github.com/circe/circe

import io.circe.parser.decode
import io.circe.syntax._

case class DataToDecode(name : String,
                        age : Int,
                        street : String,
                        buildingNumber : Int,
                        zipCode : Int, 
                        amount : Double, 
                        month : String)
object DataToDecode{
implicit val dataToDecode: Decoder[DataToDecode] = deriveDecoder

def decodeData(data: Json) : DataToDecode {
  data.as[DataToDecode].right.get
  }
}

很好的例子here

答案 1 :(得分:0)

有了Jackson,您可以这样:

import com.fasterxml.jackson.module.scala.experimental.ScalaObjectMapper

val mapper = new ObjectMapper() with ScalaObjectMapper
//this line my be needed depending on your case classes
mapper.registerModule(DefaultScalaModule)

def fromJson[T](json: String)(implicit m: Manifest[T]): T = {
    mapper.readValue[T](json)
  }

我认为Jackson lib真的很干净。 用法是这样的:

val json: String = ???
val personObject: Person = fromJson[Person](json)