英文:
How can I iterate through JSON objects even there is error using Scala Jackson
问题
以下是您提供的代码的翻译:
// 当前,jackson在属性值为空时会拒绝整个JSON。
// 我想使用com.fasterxml.jackson.*来解析JSON代码。
// 如下所示的输入JSON中,某些元素的名称属性为空。
// 因此,通过Jackson迭代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中,具有适当名称属性值的Json
[
{
"name": "Valid",
"ruleType": "validation_1",
"inputs": [ { "Name": "Test", "country": ["USA"] } ]
},
{
"name": "Valid",
"ruleType": "validation_1",
"inputs": [ { "Name": "Test", "place": ["France"] } ]
}
]
请注意,这是您提供的代码的直接翻译,无需其他解释或附加内容。如果您有更多代码部分需要翻译,请随时提供。
英文:
Currently, jackson is rejecting the whole JSON when there is blank property value.
I want to use com.fasterxml.jackson.* to parse JSON code.
As you see below input JSON, name attribute is blank some of the elements.
Hense iterate through JSON objects will ignore by Jackson.
hence there will be 2 elements formed as part of the output.
I am using below code but no luck
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)
}
//Existing Json that I want to use as input where some attribute has blank value
[
{
"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"] } ]
}
]
//New Json that will created from above which has proper name attribute value
[
{
"name": "Valid",
"ruleType": "validation_1",
"inputs": [ { "Name": "Test", "country": ["USA"] } ]
}
{
"name": "Valid",
"ruleType": "validation_1",
"inputs": [ { "Name": "Test", "place": ["France"] } ]
}
]
答案1
得分: 0
这是一个使用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
}
}
})
}
})
读取/写入JSON的方法:
def readJsonString[T](content: String)(implicit m: Manifest[T]): T = {
objectMapper.readValue(content)
}
def writeJsonString(nameRuleTypeInputsList: Seq[NameRuleTypeInputs]): String = {
// 使用漂亮的打印器以提高可读性
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
英文:
Here is one solution that would work using jackson:
Case classes to map your json to:
case class NamePlace(Name: String, country: Seq[String])
case class NameRuleTypeInputs(name: String, ruleType: String, inputs: Seq[NamePlace])
Custom serializer to include field validations before serializing:
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)
}
}
Updated your objectMapper to include the custom serializer:
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
}
}
})
}
})
Methods to 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)
}
A small test:
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))
Output:
[ {
"name" : "Valid",
"ruleType" : "validation_2",
"inputs" : [ {
"Name" : "Test",
"country" : [ "USA" ]
} ]
}, {
"name" : "Valid",
"ruleType" : "validation_1",
"inputs" : [ {
"Name" : "Test",
"country" : [ "France" ]
} ]
} ]
Useful Reference: https://www.baeldung.com/jackson-serialize-field-custom-criteria
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论