自定义JSON输出-JsonGenerator
Groovy 2.5.0增加了通过JsonGenerator
实例自定义JSON输出。 将对象转换为JSON字符串值的最简单方法是通过JsonOutput.toJson
。 此方法使用默认的JsonGenerator
,其JSON输出具有合理的默认值。 但是我们可以使用自定义生成器并创建JSON输出。 要创建自定义生成器,我们使用可通过JsonGenerator.Options
访问的构建器。 通过流式的API,我们可以例如忽略输出中带有null
值的字段,更改日期的日期格式,并按名称或值的类型忽略字段。 我们可以通过将转换的实现添加为Closure
或者实现JsonGenerator.Converter
接口来为类型添加自定义转换器。 要获取JSON字符串,我们只需调用生成器的toJson
方法。
在下面的示例Groovy代码中,我们有一个带有数据的Map
,我们想将它转换为JSON。 首先我们使用默认生成器然后创建自己的生成器来自定义JSON输出:
// Sample class to be used in JSON.
@groovy.transform.TupleConstructor
class Student {
String firstName, lastName
}
def data =
[student: new Student('Hubert', 'Klein Ikkink'),
dateOfBirth: Date.parse('yyyyMMdd', '19730709'),
website: 'https://www.mrhaki.com'.toURL(),
password: 'IamSecret',
awake: Optional.empty(),
married: Optional.of(true),
location: null,
currency: '\u20AC' /* Unicode EURO */]
import groovy.json.JsonGenerator
import groovy.json.JsonGenerator.Converter
// Default JSON generator. This generator is used by
// Groovy to create JSON if we don't specify our own.
// For this example we define the default generator
// explicitly to see the default output.
def jsonDefaultOutput = new JsonGenerator.Options().build()
// Use generator to create JSON string.
def jsonDefaultResult = jsonDefaultOutput.toJson(data) // Or use JsonOutput.toJson(data)
assert jsonDefaultResult == '{"student":{"firstName":"Hubert","lastName":"Klein Ikkink"},' +
'"dateOfBirth":"1973-07-08T23:00:00+0000","website":"https://www.mrhaki.com","password":"IamSecret",' +
'"awake":{"present":false},"married":{"present":true},"location":null,"currency":"\\u20ac"}'
// Define custom rules for JSON that will be generated.
def jsonOutput =
new JsonGenerator.Options()
.excludeNulls() // Do not include fields with value null.
.dateFormat('EEEE dd-MM-yyyy', new Locale('nl', 'NL')) // Set format for dates.
.timezone('Europe/Amsterdam') // Set timezone to be used for formatting dates.
.excludeFieldsByName('password') // Exclude fields with given name(s).
.excludeFieldsByType(URL) // Exclude fields of given type(s).
.disableUnicodeEscaping() // Do not escape UNICODE.
.addConverter(Optional) { value -> value.orElse('UNKNOWN') } // Custom converter for given type defined as Closure.
.addConverter(new Converter() { // Custom converter implemented via Converter interface.
/**
* Indicate which type this converter can handle.
*/
boolean handles(Class<?> type) {
return Student.isAssignableFrom(type)
}
/**
* Logic to convert Student object.
*/
Object convert(Object student, String key) {
"$student.firstName $student.lastName"
}
})
.build() // Create the converter instance.
// Use generator to create JSON from Map data structure.
def jsonResult = jsonOutput.toJson(data)
assert jsonResult == '{"student":"Hubert Klein Ikkink",' +
'"dateOfBirth":"maandag 09-07-1973",' +
'"awake":"UNKNOWN","married":true,"currency":"€"}'
JsonBuilder
和StreamingJsonBuilder
类现在也支持使用JsonGenerator
实例。 需要创建JSON输出时使用生成器。 使用自定义生成器不会更改构建器的内部数据结构。
在下面的示例中,我们使用前一个示例的自定义生成器,并将其应用于JsonBuilder
和StreamingJsonBuilder
实例:
import groovy.json.JsonBuilder
// We can use a generator instance as constructor argument
// for JsonBuilder. The generator is used when we create the
// JSON string. It will not effecct the internal JSON data structure.
def jsonBuilder = new JsonBuilder(jsonOutput)
jsonBuilder {
student new Student('Hubert', 'Klein Ikkink')
dateOfBirth Date.parse('yyyyMMdd', '19730709')
website 'https://www.mrhaki.com'.toURL()
password 'IamSecret'
awake Optional.empty()
married Optional.of(true)
location null
currency '\u20AC'
}
def jsonBuilderResult = jsonBuilder.toString()
assert jsonBuilderResult == '{"student":"Hubert Klein Ikkink",' +
'"dateOfBirth":"maandag 09-07-1973",' +
'"awake":"UNKNOWN","married":true,"currency":"€"}'
// The internal structure is unaffected by the generator.
assert jsonBuilder.content.password == 'IamSecret'
assert jsonBuilder.content.website.host == 'www.mrhaki.com'
import groovy.json.StreamingJsonBuilder
new StringWriter().withWriter { output ->
// As with JsonBuilder we can provide a custom generator via
// the constructor for StreamingJsonBuilder.
def jsonStreamingBuilder = new StreamingJsonBuilder(output, jsonOutput)
jsonStreamingBuilder {
student new Student('Hubert', 'Klein Ikkink')
dateOfBirth Date.parse('yyyyMMdd', '19730709')
website 'https://www.mrhaki.com'.toURL()
password 'IamSecret'
awake Optional.empty()
married Optional.of(true)
location null
currency '\u20AC'
}
def jsonStreamingBuilderResult = output.toString()
assert jsonStreamingBuilderResult == '{"student":"Hubert Klein Ikkink",' +
'"dateOfBirth":"maandag 09-07-1973",' +
'"awake":"UNKNOWN","married":true,"currency":"€"}'
}
用Groovy 2.5.0编写。