Почему toString не работает, когда String.valueOf() работает при кастинге

Мне нужно разобрать Json в структуру Map[String,String]. Json может содержать числовые и строковые типы в качестве значений.

Итак, чтобы сохранить его как строку, я применил метод toString, и он выдает ClassCastException. Однако, если применяется String.valueOf(), все в порядке.

  1. Почему так?
  2. Если есть лучший способ сделать такое литье?
import com.fasterxml.jackson.databind.ObjectMapper
import com.fasterxml.jackson.module.scala.DefaultScalaModule

import scala.collection.Map
import scala.util.parsing.json.JSON

val mapper = new ObjectMapper()
mapper.registerModule(DefaultScalaModule)


val str = "[ { \"name\": \"VehicleType\", \"value\": 11 }, { \"name\": \"VehicleWeight\", \"value\": \"12000\" } ]"
val customfields = JSON.parseFull(str) match {
  case Some(map: List[Map[String, String]]) =>
    // map.map(map => {map("name") -> map("value").toString}).toMap

    // that throws:
    // java.lang.ClassCastException: java.lang.Double cannot be cast to java.lang.String
    //  at #worksheet#.$anonfun$customfields$1.apply(scratch.scala2:14)
    //  at #worksheet#.$anonfun$customfields$1.apply(scratch.scala2:14)
    //  at scala.collection.immutable.List.map(scratch.scala2:269)
    //  at #worksheet#.customfields$lzycompute(scratch.scala2:14)

    // that works fine 
    map.map(map => {map("name") -> String.valueOf(map("value"))}).toMap
  case _ => Map.empty[String, String]
}

Я считаю, что здесь произошло следующее: первый случай match приводит результат синтаксического анализа к List[Map[String, String]], хотя это не то, что есть; из-за частичного стирания типа приведение List не терпит неудачу. В этот момент у вас есть загрязнение кучи: есть значения Double со статическим типом String, что приводит к ClassCastException, когда вы пытаетесь разыменовать одно из них.

Chris Martin 10.04.2019 04:51
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
0
1
132
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Поскольку сопоставление с образцом соответствует типу списка, но не распространяется на все типы внутри карты, поэтому вы вводите предложение Some.

Итак, вместо case Some(map: List[Map[String, String]]) =>

Попробуйте сделать это:

case Some(map: List[Map[String, _]]) =>
     map.map(map => {map("name") -> 
     map("value") match {
     case s: String => s
     case i: java.lang.Number => i
     case unexpectedType => throw Exception(s"Unexpected type $unexpectedType")
   }.toString}).toMap

Вот как вы можете безопасно обрабатывать каждое значение на карте.

Другие вопросы по теме