Это не удается, потому что play-json не понимает, как десериализовать свойство itemCounters: Map[ItemCategory, Long]
в Item
.
Действительно, карты JSON можно обрабатывать напрямую, если ключом является String
. Но это становится немного сложнее с другими структурированными объектами в ключах, такими как ItemCategory
в вопросе. Конечно, JSON с таким ключом не может быть { "repository": { "env": "demo" } }: 1
!
Итак, нам нужно четко указать десериализацию такого рода карты. Я предполагаю, что ключом для 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
).
person
Antot
schedule
25.05.2018