Anorm 解析 JSON 来自 PostgreSQL jsonb 列
Anorm parsing JSON from PostgreSQL jsonb column
我运行玩2.3,没办法更新...
当我尝试解析 jsonb 列时,出现错误 play - Cannot invoke the action, eventually got an error: java.lang.RuntimeException: UnexpectedNullableFound(ColumnName(.sports,Some(sports)))
我的代码是:
case class Sport(
id: UUID,
name: Option[String]
)
implicit val SportWrites: Writes[Sport] = Json.writes[Sport]
implicit val SportReads: Reads[Sport] = (
(JsPath \ "f1").read[UUID] and
(JsPath \ "f2").readNullable[String]
)
case class Member(
id:UUID,
name:String,
sports: List[Sport]
)
def memberParser: RowParser[Member] = {
get[UUID]("member_id") ~
get[String]("name") ~
get[JsValue]("sports") map {
case(id ~ name ~ sports) => Member(
id, name
sports.validate[List[Sport]].getOrElse(List())
)
}
}
def getMember():List[Member] = DB.WithConnection{ implicit c =>
SQL("SELECT m.id, m.name, m.sports::json from member m ").as(memberParser.*)
}
|运动|是一个 jsonb postgresql 列,如果我不将此列转换为 ::json
,我会收到 TypeDoesNotMatc
h 错误。
Json 字段被命名为 "f1"、"f2"、"f3"(...) 因为我用另一个 table 的数据填充了此列使用 JSON_AGG(...
所以它是 postgresql 命名。
此功能也有效:
def getMemberWithSports():List[Member] = DB.withConnection{ implicit c =>
SQL("""
SELECT m.member_id, m.name,
json_agg(row_to_json(row(s.sport_id, s.name))) as sports
FROM rank_member m
LEFT JOIN member_sport ms ON m.member_id = ms.member_id
LEFT JOIN sport s ON ms.sport_id = s.sport_id
GROUP BY m.member_id, m.fullname
""").as(memberParser.*)
}
这两个 SQL 命令(在 getMember() 和 getMemberWithSport() 中)的结果之间的唯一区别是,对于第一个查询,我在运动中一无所获,第二个查询(有效的那个)播放中)return JSON 填充了空值。
我目前找到的唯一解决方法是将 COALESCE 添加到 SQL 查询中,如下所示:
def getMember():List[Member] = DB.WithConnection{ implicit c =>
SQL("SELECT m.id, m.name, COALESCE(m.sports::json, '[]') as sports from member m ").as(memberParser.*)
}
我运行玩2.3,没办法更新...
当我尝试解析 jsonb 列时,出现错误 play - Cannot invoke the action, eventually got an error: java.lang.RuntimeException: UnexpectedNullableFound(ColumnName(.sports,Some(sports)))
我的代码是:
case class Sport(
id: UUID,
name: Option[String]
)
implicit val SportWrites: Writes[Sport] = Json.writes[Sport]
implicit val SportReads: Reads[Sport] = (
(JsPath \ "f1").read[UUID] and
(JsPath \ "f2").readNullable[String]
)
case class Member(
id:UUID,
name:String,
sports: List[Sport]
)
def memberParser: RowParser[Member] = {
get[UUID]("member_id") ~
get[String]("name") ~
get[JsValue]("sports") map {
case(id ~ name ~ sports) => Member(
id, name
sports.validate[List[Sport]].getOrElse(List())
)
}
}
def getMember():List[Member] = DB.WithConnection{ implicit c =>
SQL("SELECT m.id, m.name, m.sports::json from member m ").as(memberParser.*)
}
|运动|是一个 jsonb postgresql 列,如果我不将此列转换为 ::json
,我会收到 TypeDoesNotMatc
h 错误。
Json 字段被命名为 "f1"、"f2"、"f3"(...) 因为我用另一个 table 的数据填充了此列使用 JSON_AGG(...
所以它是 postgresql 命名。
此功能也有效:
def getMemberWithSports():List[Member] = DB.withConnection{ implicit c =>
SQL("""
SELECT m.member_id, m.name,
json_agg(row_to_json(row(s.sport_id, s.name))) as sports
FROM rank_member m
LEFT JOIN member_sport ms ON m.member_id = ms.member_id
LEFT JOIN sport s ON ms.sport_id = s.sport_id
GROUP BY m.member_id, m.fullname
""").as(memberParser.*)
}
这两个 SQL 命令(在 getMember() 和 getMemberWithSport() 中)的结果之间的唯一区别是,对于第一个查询,我在运动中一无所获,第二个查询(有效的那个)播放中)return JSON 填充了空值。
我目前找到的唯一解决方法是将 COALESCE 添加到 SQL 查询中,如下所示:
def getMember():List[Member] = DB.WithConnection{ implicit c =>
SQL("SELECT m.id, m.name, COALESCE(m.sports::json, '[]') as sports from member m ").as(memberParser.*)
}