es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

Comparando los tipos de datos json en tiempo de ejecución usando Jackson y Scala

Tengo un dato JSON entrante que se ve así:

{"id":"1000","premium":29999,"eventTime":"2021-12-22 00:00:00"}

Ahora, he creado una clase que aceptará este registro y verificará si el tipo de datos del registro entrante es de acuerdo a los tipos de datos definidos en la case class. Sin embargo, cuando llamo al método, siempre se ejecuta la parte Failure del caso de coincidencia.

    case class Premium(id: String, premium: Long, eventTime: String)

    class Splitter extends ProcessFunction[String, Premium] {
      val outputTag = new OutputTag[String]("failed")

      def fromJson[T](json: String)(implicit m: Manifest[T]): Either[String, T] = {
        Try {
          println("inside")
          lazy val mapper = new ObjectMapper() with ScalaObjectMapper
          mapper.registerModule(DefaultScalaModule)
          mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
          mapper.readValue[T](json)
        } match {
          case Success(x) => {
            Right(x)
          }
          case Failure(err) => {
            Left(json)
          }
        }
      }

      override def processElement(i: String, context: ProcessFunction[String, Premium]#Context, collector: Collector[Premium]): Unit = {
        fromJson(i) match {
          case Right(data) => {
            collector.collect(data)
            println("Buenos registros: " + data)
          }
          case Left(json) => {
            context.output(outputTag, json)
            println("Registros malos: " + json)
          }
        }
      }
    }

Basado en el ejemplo de registro anterior, debería pasar el valor Success pero sin importar lo que pase, siempre entra a la parte de Failure. ¿Qué más falta?

Estoy usando Scala 2.11.12 y he intentado ejemplos de este enlace y este enlace, pero sin suerte.

Tags:  , , ,

Answer

  1. Avatar for davy.ai

    El problema puede estar en el formato de fecha en los datos JSON "2021-12-22 00:00:00". Por defecto, Jackson utiliza el formato ISO-8601 para las fechas, que es "yyyy-MM-dd'T'HH:mm:ssZ". Por lo tanto, necesitamos agregar un formato de fecha personalizado para analizar correctamente la fecha. Intenta modificar tu código de la siguiente manera:

    case class Premium(id: String, premium: Long, eventTime: String)
    
    class Splitter extends ProcessFunction[String, Premium] {
      val outputTag = new OutputTag[String]("failed")
    
      val dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss")
      val mapper = new ObjectMapper() with ScalaObjectMapper
      mapper.registerModule(DefaultScalaModule)
      mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
      mapper.setDateFormat(dateFormat)
    
      def fromJson[T](json: String)(implicit m: Manifest[T]): Either[String, T] = {
        Try {
          mapper.readValue[T](json)
        } match {
          case Success(x) => {
            Right(x)
          }
          case Failure(err) => {
            Left(json)
          }
        }
      }
    
      override def processElement(i: String, context: ProcessFunction[String, Premium]#Context, collector: Collector[Premium]): Unit = {
        fromJson(i) match {
          case Right(data) => {
            collector.collect(data)
            println("Registros válidos: " + data)
          }
          case Left(json) => {
            context.output(outputTag, json)
            println("Registros no válidos: " + json)
          }
        }
      }
    }
    

    En el código anterior, estamos creando un objeto SimpleDateFormat con el formato "yyyy-MM-dd HH:mm:ss", y lo estamos estableciendo en el ObjectMapper antes de analizar los datos JSON. Esto debería resolver el problema de siempre entrar en la parte Failure del caso match.

Comments are closed.