преобразовать json строку в объект класса case из заданной json строки и типа класса case - PullRequest
0 голосов
/ 01 апреля 2020

Требуется преобразовать json строку в объект класса дела в scala с учетом jsonString и типа класса дела.

Я пробовал библиотеки Gson и Jackson, но не смог решить данную задачу. Requirment.

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 голосов
/ 02 апреля 2020

С Джексоном вы можете сделать это так:

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)
  }

Я думаю, что это действительно чисто с Джексоном Либом. Использование так:

val json: String = ???
val personObject: Person = fromJson[Person](json)
0 голосов
/ 02 апреля 2020

Попробуйте использовать circe от Cats.

  • добавьте circe в ваш проект (https://circe.github.io/circe/ - Быстрый старт).
  • создайте класс case, представляющий что вы хотите построить из вашего 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
  }
}

хороший пример здесь

...