Десериализация классов case со свойствами Map [String, Any] с помощью lift-json - PullRequest
6 голосов
/ 19 февраля 2011

Я боролся с чем-то, что должно быть простым с помощью lift-json в течение нескольких дней: сериализацией карты в JSON.

Я знаю, я знаю - «Корневой объект еще не может быть List или Map«- но сейчас я хочу завернуть в занятие, и я до сих пор не смог заставить это работать.Благодаря некоторой помощи по переполнению стека у меня работает сериализация, но я не могу десериализовать ее из строки.Я получаю сообщения об ошибках типа «Нет пригодного для использования значения для _ » и «Информация о типе неизвестна».

В Интернете есть другие более старые сообщения, в которых указано, что подсказки типа являются ответом, ноэто просто приводит к другой ошибке, такой как «Не знаю, как десериализовать _ _.»

Для Scala 2.8.0 и Lift 2.2:

import net.liftweb.json._
import net.liftweb.json.Serialization.{read, write}

case class MapWrap(data: Map[String, Any])

object Scaffold {
    def main(args: Array[String]) {

        implicit val formats = Serialization.formats(NoTypeHints)
        //implicit val formats = Serialization.formats(ShortTypeHints(List(classOf[MapWrap])))
        //implicit val formats = Serialization.formats(FullTypeHints(List(classOf[MapWrap])))

        val ser = write(new MapWrap(Map[String,Any]("key" -> "value")))
        println("JSON: " + ser)
        println(read[MapWrap](ser))

    }
}

строка println(read[MapWrap](ser)) приводит к жалобе "net.liftweb.json.MappingException: нет полезного значения для данных."

Как можно десериализовать эту оболочку класса дел (или достичь моей конечной цели: прочитать (написать (карта)("ключ" -> "значение"))))?

Ответы [ 2 ]

2 голосов
/ 10 июня 2011

Кроме того, вы можете установить параметры класса case как JObject и использовать метод .values:

import org.junit.{Test, Assert, Before}
import org.junit.Assert._
import net.liftweb.json._

case class Element(title:String, params:JObject)
@Test
class JsonParserTest{
 implicit val formats = Serialization.formats(NoTypeHints)

 @Test
  def testLiftMapToAny{
    val result = parse("""{"title":"foobar","params":{"one":1,"two":2, "other": "give"}}""").extract[Element]

    assertEquals("foobar", result.title)
    assertEquals(Map("one" -> 1, "two" -> 2, "other" -> "give"), result.params.values)
  }
}
2 голосов
/ 19 февраля 2011

Этот пример работает, если вы измените свою карту на карту [String, String].Тогда сериализатор знает, что вы ожидаете строковые значения.Подсказки типа необходимы, если значения вашей карты полиморфны.Мне нравится Карта [Строка, Животное];Собака расширяет животное;Cat расширяет Animal и т. Д. Теперь для типа Animal требуется подсказка типа.Он добавляет поле «jsonClass» в JSON, которое используется для определения конкретного типа цели.

Если вы можете перейти на 2.3-M1, вам больше не нужно оборачивать карту, но можно напрямую сериализовать карту:*

http://www.scala -tools.org / репо-релизы / net / liftweb / lift-json_2.8.1 / 2.3-M1 /

...