即使使用 Scala Jackson 出现错误,我如何遍历 JSON 个对象
How can I iterate through JSON objects even there is error using Scala Jackson
目前,jackson 拒绝整个 JSON 当有空白 属性 值时。
我想使用 com.fasterxml.jackson.* 来解析 JSON 代码。
正如你在下面输入JSON看到的,一些元素的名称属性是空白的。
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"] } ]
}
]
这是一个可以使用 jackson 的解决方案:
案例 类 将您的 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
}
}
})
}
})
方法 read/write 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
目前,jackson 拒绝整个 JSON 当有空白 属性 值时。
我想使用 com.fasterxml.jackson.* 来解析 JSON 代码。
正如你在下面输入JSON看到的,一些元素的名称属性是空白的。
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"] } ]
}
]
这是一个可以使用 jackson 的解决方案:
案例 类 将您的 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
}
}
})
}
})
方法 read/write 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