Как я могу перебирать JSON объектов, даже если есть ошибка, используя Scala Jackson - PullRequest
0 голосов
/ 06 августа 2020

В настоящее время Джексон отклоняет весь JSON, когда есть пустое значение свойства.

Я хочу использовать com.faster xml .jackson. * Для синтаксического анализа JSON кода.

Как вы видите ниже, ввод JSON, атрибут name пуст для некоторых элементов.

Hense перебирать объекты JSON будет игнорироваться Джексоном.

следовательно будет 2 элементы, сформированные как часть вывода.

Я использую приведенный ниже код, но не повезло

 def readJsonString[T](content: String)(implicit m: Manifest[T]): T = {
    val objectMapper = new ObjectMapper(new JsonFactory().enable(Feature.ALLOW_COMMENTS)) with ScalaObjectMapper
    objectMapper.registerModule(DefaultScalaModule)
    objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
    objectMapper.configure(DeserializationFeature.WRAP_EXCEPTIONS, false)
    objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
    objectMapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false)
    objectMapper.readValue(content)

  }

// Существующий Json, который я хочу использовать в качестве входных данных, если какой-либо атрибут имеет пустое значение

[
                {
                    "name": "Invalid",
                    "ruleType": "validation_1",
                    "inputs": [ { "Name": "", "country": ["USA"] } ]
                    
                },
                {
                    "name": "",
                    "ruleType": "validation_2",
                    "inputs": [ { "Name": "Test", "place": ["USA"] } ]
                    
                },
                {
                    "name": "Valid",
                    "ruleType": "validation_1",
                    "inputs": []
                    
                }
                {
                    "name": "Valid",
                    "ruleType": "validation_2",
                    "inputs": [ { "Name": "Test", "place": ["USA"] } ]
                    
                },
                {
                    "name": "Valid",
                    "ruleType": "validation_1",
                    "inputs": [ { "Name": "Test", "place": ["France"] } ]
                    
                }
        ]

// Новый Json, который будет создан сверху, который имеет значение атрибута имени собственного

[
                {
                    "name": "Valid",
                    "ruleType": "validation_1",
                    "inputs": [ { "Name": "Test", "country": ["USA"] } ]
                    
                }
                 
                {
                    "name": "Valid",
                    "ruleType": "validation_1",
                    "inputs": [ { "Name": "Test", "place": ["France"] } ]
                    
                }
        ]

1 Ответ

0 голосов
/ 08 августа 2020

Вот одно решение, которое будет работать с использованием jackson:

Классы case для сопоставления вашего json с:

  case class NamePlace(Name: String, country: Seq[String])
  case class NameRuleTypeInputs(name: String, ruleType: String, inputs: Seq[NamePlace])

Пользовательский сериализатор для включения проверок полей перед сериализацией:

  class NameRuleTypeInputsSerializer(defaultSerializer: JsonSerializer[Object]) extends JsonSerializer[NameRuleTypeInputs] {
    override def serialize(value: NameRuleTypeInputs, gen: JsonGenerator, serializers: SerializerProvider): Unit = {
      if (isValid(value)) {
        defaultSerializer.serialize(value, gen, serializers)
      }
    }

    private def isValid(value: NameRuleTypeInputs) = {
      !Option(value.name).getOrElse("").isEmpty &&
        Option(value.inputs).getOrElse(Seq.empty).nonEmpty &&
        !value.inputs.exists(i => Option(i.Name).getOrElse("").isEmpty)
    }
  }

Обновлен ваш objectMapper, чтобы включить настраиваемый сериализатор:

  val objectMapper = new ObjectMapper(new JsonFactory().enable(Feature.ALLOW_COMMENTS)) with ScalaObjectMapper
  objectMapper.registerModule(DefaultScalaModule)
  objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
  objectMapper.configure(DeserializationFeature.WRAP_EXCEPTIONS, false)
  objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
  objectMapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false)
  objectMapper.registerModule(new SimpleModule(){
    override def setupModule(context: Module.SetupContext): Unit = {
      super.setupModule(context)
      context.addBeanSerializerModifier(new BeanSerializerModifier() {
        override def modifySerializer(config: SerializationConfig, beanDesc: BeanDescription, serializer: JsonSerializer[_]): JsonSerializer[_] = {
          if(classOf[NameRuleTypeInputs] isAssignableFrom beanDesc.getBeanClass) {
            new NameRuleTypeInputsSerializer(serializer.asInstanceOf[JsonSerializer[Object]])
          } else {
            serializer
          }
        }
      })
    }
  })

Методы чтения / записи json:

  def readJsonString[T](content: String)(implicit m: Manifest[T]): T = {
    objectMapper.readValue(content)
  }

  def writeJsonString(nameRuleTypeInputsList: Seq[NameRuleTypeInputs]): String = {
    // Using pretty printer for readability
    objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(nameRuleTypeInputsList)
  }

Небольшой тест:

val testJson =
    """
        [
                {
                    "name": "Invalid",
                    "ruleType": "validation_1",
                    "inputs": [ { "Name": "", "country": ["USA"] } ]

                },
                {
                    "name": "",
                    "ruleType": "validation_2",
                    "inputs": [ { "Name": "Test", "country": ["USA"] } ]

                },
                {
                    "name": "Valid",
                    "ruleType": "validation_1",
                    "inputs": []

                },
                {
                    "name": "Valid",
                    "ruleType": "validation_2",
                    "inputs": [ { "Name": "Test", "country": ["USA"] } ]

                },
                {
                    "name": "Valid",
                    "ruleType": "validation_1",
                    "inputs": [ { "Name": "Test", "country": ["France"] } ]

                }
        ]
    """.stripMargin
  val namedRuleTypeInputs: Seq[NameRuleTypeInputs] = readJsonString[Seq[NameRuleTypeInputs]](testJson)

  println(writeJsonString(namedRuleTypeInputs))

Вывод:

[ {
  "name" : "Valid",
  "ruleType" : "validation_2",
  "inputs" : [ {
    "Name" : "Test",
    "country" : [ "USA" ]
  } ]
}, {
  "name" : "Valid",
  "ruleType" : "validation_1",
  "inputs" : [ {
    "Name" : "Test",
    "country" : [ "France" ]
  } ]
} ]

Полезная ссылка: https://www.baeldung.com/jackson-serialize-field-custom-criteria

...