Как я должен определить тип подобных JSON неструктурированных данных в Scala?

Я загрузил «intellij IDEA keybindings», сначала нажав «ctrl + shift + x», а затем выполнив поиск.

после установки, это, кажется, заставляет работать "ctrl + shift + a". Я думаю, что теперь все мои привязки клавиш являются intellij, но это небольшая цена, которую я когда-либо действительно использовал, был "ctrlshift + a"

9
задан Tim Gilbert 8 April 2009 в 07:22
поделиться

3 ответа

Вы заметили, что вы хотите, чтобы какие-то классы case моделировали ваши типы данных. На функциональных языках такие вещи называются «абстрактными типами данных», и вы можете прочитать все о том, как Haskell использует их, немного погуглив. Эквивалент Scala для ADT в Haskell использует запечатанные признаки и классы дел.

Давайте рассмотрим переписывание комбинатора синтаксического анализа JSON из стандартной библиотеки Scala или книгу «Программирование в Scala». Вместо использования Map [String, Any] для представления объектов JSON и вместо использования Any для представления произвольных значений JSON он использует абстрактный тип данных JsValue для представления значений JSON. JsValue имеет несколько подтипов, представляющих возможные виды значений JSON: JsString , JsNumber , JsObject , JsArray , JsBoolean ( JsTrue , JsFalse ), JsNull .

Манипулирование данными JSON этой формы включает в себя сопоставление с образцом. Поскольку JsValue запечатан, компилятор предупредит вас, если вы не рассмотрели все случаи. Например, код для toJson , метод, который принимает JsValue и возвращает String представление этих значений, выглядит следующим образом:

  def toJson(x: JsValue): String = x match {
    case JsNull => "null"
    case JsBoolean(b) => b.toString
    case JsString(s) => "\"" + s + "\""
    case JsNumber(n) => n.toString
    case JsArray(xs) => xs.map(toJson).mkString("[",", ","]")
    case JsObject(m) => m.map{case (key, value) => toJson(key) + " : " + toJson(value)}.mkString("{",", ","}")
  }

Сопоставление с образцом оба позволяют нам убедиться, что мы имеем дело с каждым случаем, а также «разворачивают» базовое значение из его JsType. Он предоставляет безопасный для типов способ узнать, что мы обработали каждый случай.

Кроме того, если вы знаете во время компиляции структуру данных JSON, с которыми вы имеете дело, Вы можете сделать что-то действительно крутое, как экстракторы n8han . Очень мощный материал, зацените.

14
ответ дан 4 December 2019 в 13:05
поделиться

Ну, есть несколько способов приблизиться к этому. Я бы, вероятно, просто использовал Map [String, Any] , которая должна отлично работать для ваших целей (при условии, что карта из collection.immutable , а не collection. изменяемый ). Однако, если вы действительно хотите пройти через некоторую боль, можно дать тип для этого:

sealed trait InnerData[+A] {
  val value: A
}

case class InnerString(value: String) extends InnerData[String]
case class InnerMap[A, +B](value: Map[A, B]) extends InnerData[Map[A, B]]
case class InnerBoolean(value: Boolean) extends InnerData[Boolean]

Теперь, предполагая, что вы читали поле данных JSON data в Поле Scala с именем jsData , вы бы дали этому полю следующий тип:

val jsData: Map[String, Either[Int, InnerData[_]]

Каждый раз, когда вы извлекаете поле из jsData , вам нужно будет сопоставить шаблон, проверяя, является ли значение имел тип Left [Int] или Right [InnerData [_]] (два подтипа Either [Int, InnerData [_]] ) , Когда у вас есть внутренние данные, вы должны сопоставить шаблон с с , чтобы определить, представляет ли он InnerString , InnerMap или InnerBoolean .

Технически, вы все равно должны выполнить такой тип сопоставления с образцом, чтобы использовать данные после извлечения их из JSON. Преимущество правильного подхода заключается в том, что компилятор проверит вас, чтобы убедиться, что вы не упустили никаких возможностей. Недостатком является то, что вы не можете просто пропустить невозможности (например, 'яйца' , отображающие на Int ). Кроме того, есть некоторые накладные расходы, накладываемые всеми этими объектами-обертками, так что следите за этим.

Обратите внимание, что Scala действительно позволяет вам определять псевдоним типа, который должен сократить количество LoC, необходимое для этого:

1
ответ дан 4 December 2019 в 13:05
поделиться

JSON используется в качестве примера в разделе «Программирование в Scala», в главе о синтаксическом анализе комбинатора.

1
ответ дан 4 December 2019 в 13:05
поделиться
Другие вопросы по тегам:

Похожие вопросы: