Сбой, потому что play-json не понимает, как десериализовать свойство itemCounters: Map[ItemCategory, Long]
в Item
.
Действительно, карты JSON могут обрабатываться напрямую, если ключ - String
.Но это становится немного сложнее с другими структурированными объектами в ключах, как ItemCategory
в вопросе.Конечно, JSON с таким ключом не может быть { "repository": { "env": "demo" } }: 1
!
Итак, нам нужно четко заявить о десериализации этого вида Map.Я предполагаю, что ключ для ItemCategory
является базовым значением ItemCategory.repository.env
, но это может быть любое другое свойство в зависимости от вашей эффективной модели данных.
Мы предоставляем реализацию Reads
для этого видакарты:
implicit lazy val itemCategoryMapReads = new Reads[Map[ItemCategory, Long]] {
override def reads(jsVal: JsValue): JsResult[Map[ItemCategory, Long]] = {
JsSuccess(
// the original string -> number map is translated into ItemCategory -> Long
jsVal.as[Map[String, Long]].map{
case (category, id) => (ItemCategory(Repository(category)), id)
}
)
}
}
И соответствующий Format
(с заглушкой для Writes
, которая нам сейчас не нужна):
implicit lazy val itemCategoryMapFormat = Format(itemCategoryMapReads, (catMap: Map[ItemCategory, Long]) => ???)
Базовая версия JSON теперьотображается правильно:
val strItemCat =
"""
| {
| "rep1": 1,
| "rep2": 2,
| "rep3": 3
| }
""".stripMargin
println(Json.parse(strItemCat).as[Map[ItemCategory, Long]])
// Map(ItemCategory(Repository(rep1)) -> 1, ItemCategory(Repository(rep2)) -> 2, ItemCategory(Repository(rep3)) -> 3)
Для других классов case-а, которые вы уже определили, простые форматы должны работать должным образом при условии, что они объявлены в порядке от наиболее к наименее конкретному (от Repository
до Items
).).