Использование дженериков Scala для синтаксического анализа методов json4s

#scala #generics #json4s

#scala #обобщения #json4s

Вопрос:

Я не уверен, достижимо ли это, и у меня есть очень базовое понимание того, как дженерики работают в scala. Но мне было интересно, возможно ли это. Допустим, у меня есть метод:

 case class Person(id:String,name:String)
case class Student(id:String,name:String, class:String)

    def convertToJson[A](fileName:String):{
     //read file
     parse[A]
    }
  

Возможно ли написать этот универсальный метод, который будет анализировать json на основе типа класса, который я отправляю при вызове метода convertToJson?
Что-то вроде:

 convertToJson[Student](fileName)
convertToJson[Person](fileName)
  

Кстати, приведенный выше код дает мне :

Отсутствует доступный манифест для A. ошибка.

Использование json4s для синтаксического анализа. Любая помощь приветствуется.

Ответ №1:

Это преобразует строку JSON в case class

 import org.json4s._
import org.json4s.jackson.JsonMethods._

def convertToJson[T](json: String)(implicit fmt: Formats = DefaultFormats, mf: Manifest[T]): T =
  Extraction.extract(parse(json))
  

Как только это определено, вы можете проанализировать соответствующие строки до требуемого типа:

 case class Person(id: String, name: String)
case class Student(id: String, name: String, `class`: String)

val person = convertToJson[Person]("""{"name":"Jane","id":45}""")
val student = convertToJson[Student]("""{"name":"John","id":63, "class": "101"}""")
  

Обратите внимание, что при этом будут игнорироваться данные JSON, которые не соответствуют полям в case class . Если поле в JSON является необязательным, сделайте его Option в case class , и вы получите, None если поля там нет.

Комментарии:

1. Это сработало! Спасибо. Кстати, есть ли способ устранить случай, когда у нас неверные данные? Скажем, создать исключение или что-то в этомроде?

2. @Achilleus Если у вас неверные данные, extract выдаст исключение. Вы можете позволить вызывающей стороне обработать это или обернуть extract вызов в Try и вернуть Try[T] , что, возможно, более стандартно в Scala.

3. На самом деле, это не вызовет исключения в ситуации, когда мы имеем дело с вложенным json и объект в нем, скажем, имеет поле, написанное неправильно. Он просто обнулит этот объект и продолжит работу. Мне было интересно, можем ли мы каким-то образом указать, что это сбой, или выдать исключение вместо того, чтобы обнулять его.

4. Можете ли вы привести пример этого? Если я переименую одно из полей из строки JSON, я получу MappingException: No usable value for <fieldname> .

5. На самом деле, это создает исключение для классов case. Но я использую класс регистра записей, специфичный для Avro. Это класс case, который расширяет org.apache.avro.specific.SpecificRecordBase. Но каким-то образом в этом случае он сериализуется до null.