java—即使在使用scala时出错,我如何迭代json对象

dhxwm5r4  于 2021-05-27  发布在  Spark
关注(0)|答案(1)|浏览(451)

目前,jackson拒绝了整个json,因为属性值为空。
我想使用com.fasterxml.jackson.*来解析json代码。
正如您在下面的input json中看到的,name属性在某些元素中是空的。
hense迭代json对象将被jackson忽略。
因此,将有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"] } ]

                }
        ]
guykilcj

guykilcj1#

下面是一个使用jackson的解决方案:
要将jsonMap到的case类:

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

相关问题