将 JSON 数组解组到案例类列表时出错 c
Errors Unmarshalling JSON array to List of case classesc
我一直在尝试使用 circe
将 JSON 从外部服务解编为案例列表 classes(我是 circe
和 circe
的初学者斯卡拉)。
案例class如下:
case class User(
id: Int,
username: Option[String],
permalink_url: Option[String],
avatar_url: Option[String],
tracks: Option[List[Track]],
favorites: Option[List[Track]],
followings: Option[List[User]] // The JSON below would populate this field
)
到目前为止,我对所有其他类型都使用了自动派生,但是这个使用了结构
{
"collection": [
{
"id": 42,
"username": "user",
"permalink_url": "foo://bar.baz",
"followers_count": 15089,
"followings_count": 498,
"reposts_count": 31,
"comments_count": 13,
"online": false,
"likes_count": 0,
"playlist_count": 10
},
...etc, etc
]
}
为了解决这个问题,我实现了一个自定义解码器:
implicit val followingsDecoder: Decoder[List[User]] = Decoder.instance( c =>
for {
collection <- c.downField("collection").as[List[User]]
} yield collection
)
这会失败并产生以下错误:
DecodingFailure(CNil, List(DownField(collection)))
我也尝试过使用 circe
的自动解码器推导,这会产生不同的错误:
DecodingFailure(CanBuildFrom for A, List())
我了解 circe
的错误消息未提供解码失败的字段。我不需要 User
案例 class 中未指定的任何字段,并且不确定这是否与我收到的 JSON 或我的方式有关试图解码它。
这里有我遗漏的东西吗?我已经尝试了其他解码方法,例如半自动推导以及尝试将列表解组到它自己的案例 class 中。
implicit val followingsDecoder: Decoder[List[User]] = deriveDecoder[List[User]].prepare(
_.downField("collection")
)
我在这里遗漏了什么吗?我如何将此 JSON 解析为案例列表 classes?
User
的大小写 class 定义是有效的,但使用隐式 followingsDecoder: Decoder
不是强制解组的。 collection
也可以包装成 case class
并且解码将自动完成。所以,如果我们有
case class UsersCollection(collection: List[User])
// I also added this one to make it compile:
case class Track(id: Int)
和原始 json,添加了 followings
字段:
private val json =
"""
|{
| "collection": [
| {
| "id": 42,
| "username": "user",
| "permalink_url": "foo://bar.baz",
| "followers_count": 15089,
| "followings_count": 498,
| "reposts_count": 31,
| "comments_count": 13,
| "online": false,
| "likes_count": 0,
| "playlist_count": 10,
| "followings": [
| { "id": 43 },
| { "id": 44 },
| { "id": 45 }
| ]
| }
| ]
| }
""".stripMargin
正确解析:
val decoded = decode[UsersCollection](json)
println(decoded)
// Right(UsersCollection(List(
// User(42,Some(user),Some(foo://bar.baz),None,None,None,
// Some(List(User(43,None,None,None,None,None,None),
// User(44,None,None,None,None,None,None),
// User(45,None,None,None,None,None,None)))))))
因此,如果您的情况可行,我建议添加另一个临时案例 class 包装用户列表,而不是使用自定义解码器。
我一直在尝试使用 circe
将 JSON 从外部服务解编为案例列表 classes(我是 circe
和 circe
的初学者斯卡拉)。
案例class如下:
case class User(
id: Int,
username: Option[String],
permalink_url: Option[String],
avatar_url: Option[String],
tracks: Option[List[Track]],
favorites: Option[List[Track]],
followings: Option[List[User]] // The JSON below would populate this field
)
到目前为止,我对所有其他类型都使用了自动派生,但是这个使用了结构
{
"collection": [
{
"id": 42,
"username": "user",
"permalink_url": "foo://bar.baz",
"followers_count": 15089,
"followings_count": 498,
"reposts_count": 31,
"comments_count": 13,
"online": false,
"likes_count": 0,
"playlist_count": 10
},
...etc, etc
]
}
为了解决这个问题,我实现了一个自定义解码器:
implicit val followingsDecoder: Decoder[List[User]] = Decoder.instance( c =>
for {
collection <- c.downField("collection").as[List[User]]
} yield collection
)
这会失败并产生以下错误:
DecodingFailure(CNil, List(DownField(collection)))
我也尝试过使用 circe
的自动解码器推导,这会产生不同的错误:
DecodingFailure(CanBuildFrom for A, List())
我了解 circe
的错误消息未提供解码失败的字段。我不需要 User
案例 class 中未指定的任何字段,并且不确定这是否与我收到的 JSON 或我的方式有关试图解码它。
这里有我遗漏的东西吗?我已经尝试了其他解码方法,例如半自动推导以及尝试将列表解组到它自己的案例 class 中。
implicit val followingsDecoder: Decoder[List[User]] = deriveDecoder[List[User]].prepare(
_.downField("collection")
)
我在这里遗漏了什么吗?我如何将此 JSON 解析为案例列表 classes?
User
的大小写 class 定义是有效的,但使用隐式 followingsDecoder: Decoder
不是强制解组的。 collection
也可以包装成 case class
并且解码将自动完成。所以,如果我们有
case class UsersCollection(collection: List[User])
// I also added this one to make it compile:
case class Track(id: Int)
和原始 json,添加了 followings
字段:
private val json =
"""
|{
| "collection": [
| {
| "id": 42,
| "username": "user",
| "permalink_url": "foo://bar.baz",
| "followers_count": 15089,
| "followings_count": 498,
| "reposts_count": 31,
| "comments_count": 13,
| "online": false,
| "likes_count": 0,
| "playlist_count": 10,
| "followings": [
| { "id": 43 },
| { "id": 44 },
| { "id": 45 }
| ]
| }
| ]
| }
""".stripMargin
正确解析:
val decoded = decode[UsersCollection](json)
println(decoded)
// Right(UsersCollection(List(
// User(42,Some(user),Some(foo://bar.baz),None,None,None,
// Some(List(User(43,None,None,None,None,None,None),
// User(44,None,None,None,None,None,None),
// User(45,None,None,None,None,None,None)))))))
因此,如果您的情况可行,我建议添加另一个临时案例 class 包装用户列表,而不是使用自定义解码器。