我来自Java背景,试图了解如何在Scala中为Domain类/ POJO建模。
我正在尝试从RestAPI反序列化JSON响应,我的Java POJO如下:
@Data
public class ColumnResponse {
private String id;
private String name;
private String type;
...
}
k
@Data
public class DataSetGetResponse {
private String id;
private List<ColumnResponse> columns;
...
}
现在我创建了以下案例类
case class DataSetGetResponse (id: String,
columns: List[ColumnResponse]
.... )
case class ColumnResponse (id: String,name: String ...)
我正在尝试使用https://sttp.readthedocs.io/en/latest/json.html#json4s库进行HTTP通信,并使用json4s进行反序列化。
问题:
1)在DataSetGetResponse案例类中,字段“ columns”是一个List。默认情况下,这是一个不可变的列表。反序列化库如何将新的DataColumnGetResponse对象添加到此不可变列表?我必须宣布这是可变的吗?
2)ColumnResponse POJO中有一个称为“类型”的字段。在Scala中,“ type”是保留关键字。如何处理这种情况?
答案 0 :(得分:4)
回答第一个:
可以使用copy
函数对不可变的对象进行突变:
dataSet.copy(columns = newResp :: dataSet.columns)
对于更复杂的任务,您可以使用 Lenss 参见此处的示例:enter link description here
回答第二个问题:
如果是保留字,您可以像
case class ColumnResponse (id: String, name: String, `type`: String)
答案 1 :(得分:1)
此答案解决了问题的以下方面:
反序列化库如何添加新的DataColumnGetResponse对象 到这个不可变的清单?
让我们考虑一下该问题的简化版本:
JsonMethods.parse("""[1,2,3]""").extract[List[Int]]
json4s如何将[1,2,3]
反序列化为不可变的List[Int]
?首先,将原始字符串parses插入中间AST(抽象语法树)数据结构中,在该数据结构中,它像这样表示列表
case class JArray(arr: List[JValue]) extends JValue
我们在这里看到arr
是不可变的列表。 parse
执行后建立它的关键行在JsonParser
def newValue(v: JValue): Unit = {
...
case a: JArray => vals.replace(JArray(v :: a.arr))
...
}
请注意,v :: a.arr
中的运算符::
在此列表的开头添加元素,并返回添加了v
的 new 列表。这意味着由于[1,2,3]
中包含三个元素,因此以下三个列表是由json4s在反序列化过程中创建的
JArray(List(JInt(1))
JArray(List(JInt(2), JInt(1)))
JArray(List(JInt(3), JInt(2), JInt(1)))
再次注意,这是三个单独列表。
接下来,在创建内部AST之后,实际的deserialisation至List[Int]
通过调用extract[List[Int]]
进行。对列表执行此操作的关键组件是CollectionBuilder
private class CollectionBuilder(json: JValue, tpe: ScalaType)(implicit formats: Formats) {
...
val array: Array[_] = json match {
case JArray(arr) => arr.map(extractDetectingNonTerminal(_, typeArg)).toArray
...
}
请注意,我们如何简单地映射到在解析步骤中建立的AST arr
并将每个元素转换为类型typeArg
的模型,在我们的简单情况下为Int
,但在您的情况下应该是DataColumnGetResponse
。