Nano Hash - криптовалюты, майнинг, программирование

Воспроизведение средства форматирования JSON для класса case с классами универсального типа

Попытка написать средство форматирования json для этого класса case

case class OptionRange[+T](start: Option[T], end: Option[T])

Это то, что у меня есть до сих пор

implicit def fmt[T <: OptionRange[_]](implicit fmt: Format[Option[T]]): Format[OptionRange[T]] = new Format[OptionRange[T]] {
  def reads(json: JsValue): JsSuccess[OptionRange[T]] = JsSuccess(new OptionRange[T] (
    (json \ "start").as[Option[T]],
    (json \ "end").as[Option[T]]
  ))
  def writes(i: OptionRange[T]) = JsObject(Seq(
    "start" -> Json.toJson(i.start),
    "end" -> Json.toJson(i.end)
  ))
}

Этот фрагмент кода компилируется, но когда я пытаюсь отформатировать OptionRange[Int], я получаю сообщение об ошибке, что нет доступного неявного формата.

Как я могу написать формат, который будет доступен в неявной области видимости?


  • обратите внимание, что .as[Option[T]] не является идиоматическим способом сделать это в Play-Json. .readNullable[T] предпочтительнее. Он автоматически поднимет ваш T в Option 02.12.2016
  • На самом деле @LouisF. .readNullable[T] — это метод, который доступен на JsPath, а не на JsValue... см. мой ответ ниже 22.01.2019

Ответы:


1

У вас есть немного циклического определения типа.

Мне кажется, что в данном случае вы намереваетесь T оценить как Int. Однако в определении функции вы ограничили [T <: OptionRange[_]]. Итак, Scala считает, что T должно быть OptionRange чего-то.

Это становится еще сложнее, когда вы переходите к неявному параметру функции (implicit fmt: Format[Option[T]]). Если T равно OptionRange[_], то вы сообщаете компилятору, что требуется Format[Option[OptionRange[_]]] вместо Format[Option[_]]. Ваша функция не может быть источником этого Format, так как она не может быть оценена, чтобы обеспечить неявное требование.

Решение состоит в том, чтобы перестать ограничивать T.

implicit def fmt[T](implicit fmt: Format[Option[T]]) ...

Затем, когда вы пытаетесь отформатировать OptionRange как json:

scala> import play.api.libs.json._
import play.api.libs.json._

scala> case class OptionRange[+T](start: Option[T], end: Option[T])
defined class OptionRange

scala> implicit def fmt[T](implicit fmt: Format[Option[T]]): Format[OptionRange[T]] = new Format[OptionRange[T]] {
     |   def reads(json: JsValue): JsSuccess[OptionRange[T]] = JsSuccess(new OptionRange[T] (
     |     (json \ "start").as[Option[T]],
     |     (json \ "end").as[Option[T]]
     |   ))
     |   def writes(i: OptionRange[T]) = JsObject(Seq(
     |     "start" -> Json.toJson(i.start),
     |     "end" -> Json.toJson(i.end)
     |   ))
     | }
fmt: [T](implicit fmt: play.api.libs.json.Format[Option[T]])play.api.libs.json.Format[OptionRange[T]]

scala> Json.toJson(OptionRange(Some(1), Some(2)))
res0: play.api.libs.json.JsValue = {"start":1,"end":2}
01.12.2016
  • Можете ли вы сообщить мне все, что вы набрали в консоли? Я не могу повторить то, что ты умеешь. Кроме того, какую версию play-json вы использовали? 02.12.2016
  • @adamtrousdale Кажется, я использую play-json версии 2.3.8. Однако здесь это не должно иметь значения. 02.12.2016
  • @adamtrousdale Кроме того, я обновил свой ответ, чтобы получить код, который я ввел в консоль scala. 02.12.2016
  • Я не получаю то же самое в своей консоли, я получаю scala> Json.toJson(OptionRange(Some(1), Some(2))) <console>:22: error: No Json serializer found for type OptionRange[Int]. Try to implement an implicit Writes or Format for this type. Json.toJson(OptionRange(Some(1), Some(2))) 02.12.2016
  • Не могли бы вы как-нибудь показать мне, что именно вы печатаете и видите в консоли scala после каждой записи? Вы пытались указать fmt вручную, не оставляя его для неявного разрешения? 02.12.2016
  • Введите scala> import play.api.libs.json._, см. import play.api.libs.json._ 06.12.2016
  • Введите scala> case class OptionRange[+T](start: Option[T], end: Option[T]), см. defined class OptionRange 06.12.2016
  • Введите implicit def fmt[T](implicit fmt: Format[Option[T]]): Format[OptionRange[T]] = new Format[OptionRange[T]] { def reads(json: JsValue): JsSuccess[OptionRange[T]] = JsSuccess(new OptionRange[T] ( (json \ "start").as[Option[T]], (json \ "end").as[Option[T]] )) def writes(i: OptionRange[T]) = JsObject(Seq( "start" -> Json.toJson(i.start), "end" -> Json.toJson(i.end) )) }, см. error: missing or invalid dependency detected while loading class file 'Json.class'. 06.12.2016
  • извините, форматирование плохое. После того, как я импортирую Json.class из play.api.libs.api.json, я получаю еще одну ошибку и должен импортировать Writes.class. Затем при попытке определить мой форматтер я получаю сообщение об ошибке, говорящее о том, что файл класса Reads.class отсутствует. После импорта и попытки определить снова я получаю отсутствующую ошибку JsResult.class. После импорта я могу успешно определить свой форматтер. Однако попытка сделать Json.toJson(OptionRange(Some(1), Some(2))) по-прежнему приводит к той же ошибке выше No Json serializer found 06.12.2016
  • Похоже, это должно работать без каких-либо проблем с отсутствующими классами и т. д. 06.12.2016
  • Это невероятно странно. Что же такое правильный импорт, который вам нужно выполнить? Эти классы были перемещены в вашу версию play-json? 06.12.2016
  • Это очень странно, я не могу понять, почему я должен импортировать эти классы по отдельности. Я пробовал с play-json 2.3.8, но у меня были те же проблемы. Что мне нужно было сделать, так это импортировать каждый класс (Json.class, Writes.class, Reads.class, JsResult.class), каждый в пакете play.api.libs.json, но не импортированный с помощью первого оператора импорта import play.api.libs.json._ 07.12.2016
  • Как это поведет себя, если вы измените свой реальный код, а не попытаетесь сделать это в консоли Scala? 08.12.2016

  • 2

    Вот как это сделать с помощью play-framework 2.3.9, Scala 2.11.8:

    import play.api.libs.json._ // JSON library
    import play.api.libs.json.Reads._ // Custom validation helpers
    import play.api.libs.functional.syntax._ // Combinator syntax
    
    case class OptionRange[+T](start: Option[T], end: Option[T])
    
    object Hello extends App {
    
      implicit def formatOptionRange[T](implicit formatT: Format[T]): Format[OptionRange[T]] = 
        (
          (JsPath \ "start").formatNullable[T] and
          (JsPath \ "end").formatNullable[T]
        )(OptionRange.apply, unlift(OptionRange.unapply))
    
        println(Json.toJson(OptionRange(Some(1), Some(2))))
    }
    
    //Prints:
    //{"start":1,"end":2}
    

    Вот документация по формату .

    21.01.2019
    Новые материалы

    Кластеризация: более глубокий взгляд
    Кластеризация — это метод обучения без учителя, в котором мы пытаемся найти группы в наборе данных на основе некоторых известных или неизвестных свойств, которые могут существовать. Независимо от..

    Как написать эффективное резюме
    Предложения по дизайну и макету, чтобы представить себя профессионально Вам не позвонили на собеседование после того, как вы несколько раз подали заявку на работу своей мечты? У вас может..

    Частный метод Python: улучшение инкапсуляции и безопасности
    Введение Python — универсальный и мощный язык программирования, известный своей простотой и удобством использования. Одной из ключевых особенностей, отличающих Python от других языков, является..

    Как я автоматизирую тестирование с помощью Jest
    Шутка для победы, когда дело касается автоматизации тестирования Одной очень важной частью разработки программного обеспечения является автоматизация тестирования, поскольку она создает..

    Работа с векторными символическими архитектурами, часть 4 (искусственный интеллект)
    Hyperseed: неконтролируемое обучение с векторными символическими архитектурами (arXiv) Автор: Евгений Осипов , Сачин Кахавала , Диланта Хапутантри , Тимал Кемпития , Дасвин Де Сильва ,..

    Понимание расстояния Вассерштейна: мощная метрика в машинном обучении
    В обширной области машинного обучения часто возникает необходимость сравнивать и измерять различия между распределениями вероятностей. Традиционные метрики расстояния, такие как евклидово..

    Обеспечение масштабируемости LLM: облачный анализ с помощью AWS Fargate и Copilot
    В динамичной области искусственного интеллекта все большее распространение получают модели больших языков (LLM). Они жизненно важны для различных приложений, таких как интеллектуальные..