Scala:对具有不同数据类型但模式相同的json文件的Json排序操作

时间:2018-11-20 06:22:28

标签: json scala spray-json

我有一个json文件,其中包含用于存储和在线的两种数据类型。但是几列的数据类型不同,但是列名和架构相同。 我想对json进行一些操作,例如使用Scala中的spray joson库进行排序,重新排列。但是由于“ storeId”和“ amount”的数据类型不同,因此无法在josn上应用案例类。 有什么办法可以重写case类来处理整数和字符串?

示例:我将它们存储在文件中,逐行读取并将其分配给字符串

Given inputJosn String : { "purchaseType": "1", "purchaseChannel": "store", "storeId": 6167, "paymentType": [{ "type": "CASH", "category": "Cash", "amount": 3.91 }] }, { "purchaseType": "2", "purchaseChannel": "online", "storeId": "6168", "paymentType": [{ "type": "Card", "category": "Card", "amount": "5.04" }] }

代码:

import spray.json._
import DefaultJsonProtocol._

case class payType(`type`:String,category:String,amount:String)
case class Transactions(purchaseType:String,purchaseChannel:String,storeId:String,paymentType: payType )

object MyJsonpayType extends DefaultJsonProtocol {
implicit val payTypeFormat: JsonFormat[payType] = jsonFormat3(payType)
}
import MyJsonpayType._

object MyJsonTransactions extends DefaultJsonProtocol {
implicit val TransactionsFormat: JsonFormat[Transactions] = jsonFormat4(Transactions)
}
import MyJsonTransactions._



inputJosn.parseJson.convertTo[Transactions]

抛出错误,说要结束JsString,但得到了6167。

我知道为什么会引发错误,但是这些是用更好的方式重新编写case类以处理整数和字符串的任何方式。

2 个答案:

答案 0 :(得分:2)

您可以像

一样使用Either。
case class payType(`type`:String,category:String,amount:Either[Double,String]) 

但是,您只是将罐子踢了下去。如果必须对数量字段进行排序,汇总等操作,则需要对数据进行规范化。

如果是这种情况,我最好为具有单一类型的对象编写自定义反序列化。

答案 1 :(得分:0)

在这种情况下,我喜欢使用Jackson库,但是在这种情况下,您可以仅调用storeIdstring。之后,您可以使用伴随对象将其解析为long

尝试一下:

case class Transactions (
  purchaseType:String,
  purchaseChannel:String,
  storeId:String,
  paymentType: payType ) {

  def storeIdToLong(t: Transaction) = TransactionsAsLong(
    purchaseType = t.purchaseType,
    purchaseChannel = t.purchaseChannel,
    storeId = t.storeId.toLong,
    paymentType = t.paymentType
  )
}

case class TransactionsAsLong (
  purchaseType:String,
  purchaseChannel:String,
  storeId:Long,
  paymentType: payType )


object Transactions {
  implicit def transactions_to_long(t: Transactions): TransactionsAsLong = t.storeIdToLong()
}

现在,您可以根据需要编写val test: Transaction = TransactionsAsLong(...)

我建议改写自定义解串器:-)