使用Argonaut创建通用JSON转换器

 大眼妹886 发布于 2023-02-06 19:42

我是Scala的新手,在这里我正在尝试创建一个基于Argonaut的通用json转换器.我试图搜索谷歌和stackoverflow,但到目前为止,我没有任何线索.

这是我的代码片段.

import org.springframework.http.converter.AbstractHttpMessageConverter
import org.springframework.http.{MediaType, HttpInputMessage, HttpOutputMessage}    
import scala.io.Source
import argonaut._,Argonaut._

case class Currency(code: String)
object Currency {
    implicit def CurrencyCodecJson: CodecJson[Currency] = casecodec1(Currency.apply, Currency.unapply)("code")
}

case class Person(firstName: String, lastName: String)
object Person {
    implicit def PersonCodecJson: CodecJson[Person] = casecodec2(Person.apply, Person.unapply)("firstName", "LastName")
}

class ArgonautConverter extends AbstractHttpMessageConverter[Object](new MediaType("application", "json", Charset.forName("UTF-8")), new MediaType("application", "*+json", Charset.forName("UTF-8"))) {
    val c = classOf[Currency]
    val p = classOf[Person]

    def writeInternal(t: Object, outputStream: OutputStream) = {
        val jsonString = t match {
            case c:Currency => c.asJson.ToString()
            case p:Person => p.asJson.ToString()
    }

    def supports(clazz: Class[_]): Boolean = clazz.isAssignableFrom(classOf[CodecJson])// clazz == classOf[Currency] || clazz == classOf[LegalEntity]

    def readInternal(clazz: Class[_ <: Object], inputStream: InputStream): Object = {
        val jsonString = Source.fromInputStream(inputStream).getLines.mkString
        val jsonObject = clazz match {
            case `c` => jsonString.decodeOption[Currency]
            case `p` => jsonString.decodeOption[Person]
        }
        jsonObject match {
            case Some(j) => j
            case None => null
        }
    }
}

我想要做的是概括,以便我不需要为将来添加的每个新模型类(如本例中的Currency和Person)添加匹配项.

1 个回答
  • Argonaut已经具有通用编码和解码功能.

    例如,Parse.decodeOption将String解析为您具有编解码器的任何类型.

    你要做的是在运行时决定你是否有一个类型的编解码器,但你可以让编译器为你解决这个问题.

    是否可以解码为类型T取决于是否存在DecodeJson[T]范围内的隐式实例.(这是一个超类型CodecJson[T],你写了几个,所以他们很好.)

    不幸的是,编译器不会为您推断出这个约束,因此您必须在类型签名中提及它.一种方法是使用上下文绑定,这T : DecodeJson在下面的示例中.

    def read[T : DecodeJson](inputStream: InputStream): Option[T] = {
      val jsonString = Source.fromInputStream(inputStream).getLines.mkString
      Parse.decodeOption(jsonString)
    }
    

    (另请注意,您应该返回Option[T]而不是使用null.)

    同样,write可以使用签名实现:

    def write[T : EncodeJSON](t: T, outputStream: OutputStream)
    

    您的CodecJson[T]实例也是实例EncodeJson[T].

    2023-02-06 19:44 回答
撰写答案
今天,你开发时遇到什么问题呢?
立即提问
热门标签
PHP1.CN | 中国最专业的PHP中文社区 | PNG素材下载 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有