Groovy json 包
学习任何一门语言,我都看重 json 的操作是否顺手方便,毕竟 json 是现在最流行的数据交换格式。
JsonOutput
官方定义:
一个提供 JSON 结构的字符串序列化类,可以将各种类型变成字符串,但不提供自定义结果输出的能力,如果需要更改结果输出的能力可以使用下面会提到的 JsonGenerator
def list = [1,2,4,5]
def json = JsonOutput.toJson(list)
println json
println JsonOutput.prettyPrint(json)
输出:
[1,2,4,5]
[
1,
2,
4,
5
]
源码
使用了一个默认的JsonGenerator来提供 json 能力
static final JsonGenerator DEFAULT_GENERATOR = new DefaultJsonGenerator(new JsonGenerator.Options());
public static String toJson(Object object) {
return DEFAULT_GENERATOR.toJson(object);
}
/**
* @return a JSON object representation for a map
*/
public static String toJson(Map m) {
return DEFAULT_GENERATOR.toJson(m);
}
JsonGenerator
官方定义:
从对象生成 Json,JsonGenerator.Options 构建器可用于配置 JsonGenerator 的实例。(自定义)
源码
public interface JsonGenerator {
/**
* 将一个对象转换成JSON字符串.
*
* @param object to convert to JSON
* @return JSON
*/
String toJson(Object object);
/**
* 判断配置是否排除了给定的这个字段
*
* @param name of the field
* @return true if that field is being excluded, else false
*/
boolean isExcludingFieldsNamed(String name);
/**
* 判断配置是否排除了给定的这个值
*
* @param value an instance of an object
* @return true if values like this are being excluded, else false
*/
boolean isExcludingValues(Object value);
/**
* 处理类型转换
*
* @since 2.5.0
*/
interface Converter {
/**
* 给定一个类型,如果这个类型能被转换器处理,那么返回true
* @param type the type of the object to convert
* @return {@code true} if this converter can successfully convert values of
* the given type, else {@code false}
*/
boolean handles(Class<?> type);
/**
* 进行对象转换
*
* @param value the object to convert
* @param key the key name for the value, may be {@code null}
* @return the converted object
*/
Object convert(Object value, String key);
}
/**
* A builder used to construct a {@link JsonGenerator} instance that allows
* control over the serialized JSON output. If you do not need to customize the
* output it is recommended to use the static {@code JsonOutput.toJson} methods.
*
*/
class Options {
protected static final String JSON_DATE_FORMAT = "yyyy-MM-dd'T'HH🇲🇲ssZ";
protected static final Locale JSON_DATE_FORMAT_LOCALE = Locale.US;
protected static final String DEFAULT_TIMEZONE = "GMT";
protected boolean excludeNulls;
protected boolean disableUnicodeEscaping;
protected String dateFormat = JSON_DATE_FORMAT;
protected Locale dateLocale = JSON_DATE_FORMAT_LOCALE;
protected TimeZone timezone = TimeZone.getTimeZone(DEFAULT_TIMEZONE);
protected final Set<Converter> converters = new LinkedHashSet<Converter>();
protected final Set<String> excludedFieldNames = new HashSet<String>();
protected final Set<Class<?>> excludedFieldTypes = new HashSet<Class<?>>();
public Options() {}
/**
* 不序列化null值
*
* @return a reference to this {@code Options} instance
*/
public Options excludeNulls() {
excludeNulls = true;
return this;
}
/**
* Disables the escaping of Unicode characters in JSON String values.
*
* @return a reference to this {@code Options} instance
*/
public Options disableUnicodeEscaping() {
disableUnicodeEscaping = true;
return this;
}
/**
* Sets the date format that will be used to serialize {@code Date} objects.
* This must be a valid pattern for {@link java.text.SimpleDateFormat} and the
* date formatter will be constructed with the default locale of {@link Locale#US}.
*
* @param format date format pattern used to serialize dates
* @return a reference to this {@code Options} instance
* @exception NullPointerException if the given pattern is null
* @exception IllegalArgumentException if the given pattern is invalid
*/
public Options dateFormat(String format) {
return dateFormat(format, JSON_DATE_FORMAT_LOCALE);
}
/**
* Sets the date format that will be used to serialize {@code Date} objects.
* This must be a valid pattern for {@link java.text.SimpleDateFormat}.
*
* @param format date format pattern used to serialize dates
* @param locale the locale whose date format symbols will be used
* @return a reference to this {@code Options} instance
* @exception IllegalArgumentException if the given pattern is invalid
*/
public Options dateFormat(String format, Locale locale) {
// validate date format pattern
new SimpleDateFormat(format, locale);
dateFormat = format;
dateLocale = locale;
return this;
}
/**
* Sets the time zone that will be used to serialize dates.
*
* @param timezone used to serialize dates
* @return a reference to this {@code Options} instance
* @exception NullPointerException if the given timezone is null
*/
public Options timezone(String timezone) {
this.timezone = TimeZone.getTimeZone(timezone);
return this;
}
/**
* Registers a converter that will be called when a type it handles is encountered.
*
* @param converter to register
* @return a reference to this {@code Options} instance
*/
public Options addConverter(Converter converter) {
if (converter != null) {
converters.add(converter);
}
return this;
}
/**
* Registers a closure that will be called when the specified type or subtype
* is serialized.
*
* <p>The closure must accept either 1 or 2 parameters. The first parameter
* is required and will be instance of the {@code type} for which the closure
* is registered. The second optional parameter should be of type {@code String}
* and, if available, will be passed the name of the key associated with this
* value if serializing a JSON Object. This parameter will be {@code null} when
* serializing a JSON Array or when there is no way to determine the name of the key.
*
* <p>
* Example:
* <pre><code class="groovyTestCase">
* def generator = new groovy.json.JsonGenerator.Options()
* .addConverter(URL) { URL u {@code ->}
* u.getHost()
* }
* .build()
*
* def input = [domain: new URL('http://groovy-lang.org/json.html#_parser_variants')]
*
* assert generator.toJson(input) == '{"domain":"groovy-lang.org"}'
* </code></pre>
*
* <p>If two or more closures are registered for the exact same type the last
* closure based on the order they were specified will be used. When serializing an
* object its type is compared to the list of registered types in the order the were
* given and the closure for the first suitable type will be called. Therefore, it is
* important to register more specific types first.
*
* @param type the type to convert
* @param closure called when the registered type or any type assignable to the given
* type is encountered
* @param <T> the type this converter is registered to handle
* @return a reference to this {@code Options} instance
* @exception NullPointerException if the given type or closure is null
* @exception IllegalArgumentException if the given closure does not accept
* a parameter of the given type
*/
public <T> Options addConverter(Class<T> type,
@ClosureParams(value=FromString.class, options={"T","T,String"})
Closure<?> closure)
{
Converter converter = new DefaultJsonGenerator.ClosureConverter(type, closure);
converters.remove(converter);
return addConverter(converter);
}
/**
* Excludes from the output any fields that match the specified names.
*
* @param fieldNames name of the field to exclude from the output
* @return a reference to this {@code Options} instance
*/
public Options excludeFieldsByName(CharSequence... fieldNames) {
return excludeFieldsByName(Arrays.asList(fieldNames));
}
/**
* Excludes from the output any fields that match the specified names.
*
* @param fieldNames collection of names to exclude from the output
* @return a reference to this {@code Options} instance
*/
public Options excludeFieldsByName(Iterable<? extends CharSequence> fieldNames) {
for (CharSequence cs : fieldNames) {
if (cs != null) {
excludedFieldNames.add(cs.toString());
}
}
return this;
}
/**
* Excludes from the output any fields whose type is the same or is
* assignable to any of the given types.
*
* @param types excluded from the output
* @return a reference to this {@code Options} instance
*/
public Options excludeFieldsByType(Class<?>... types) {
return excludeFieldsByType(Arrays.asList(types));
}
/**
* Excludes from the output any fields whose type is the same or is
* assignable to any of the given types.
*
* @param types collection of types to exclude from the output
* @return a reference to this {@code Options} instance
*/
public Options excludeFieldsByType(Iterable<Class<?>> types) {
for (Class<?> c : types) {
if (c != null) {
excludedFieldTypes.add(c);
}
}
return this;
}
/**
* Creates a {@link JsonGenerator} that is based on the current options.
*
* @return a fully configured {@link JsonGenerator}
*/
public JsonGenerator build() {
return new DefaultJsonGenerator(this);
}
}
}
使用
static void main(String[] args) {
def list = ["name": "wang", "age": 99,"list":[1,2,3,4]]
def build = new JsonGenerator.Options()
.excludeFieldsByType(Number) //排除数字类型的字段
.excludeFieldsByName('name') //排除字段名为name的字段
.addConverter(List) { List u -> //添加一个转换器 将List类型的字段转换成取List第一个值
u.get(0)
}
.build()
println build.toJson(list)
}
// 结果
// {"list":1}
JsonBuilder
通过简单语法来构造 json 对象,在 groovy 里面不想再用 fastjson 了嗷
使用
static void main(String[] args) {
def exp = '''{
"x": {
"person": {
"firstName": "Guillame",
"lastName": "Laforge",
"address": {
"city": "Paris",
"country": "France",
"zip": {
"af": "a"
}
},
"married": true,
"conferences": [
{
"a": "JavaOne"
},
{
"a": "Gr8conf"
}
]
}
}
}'''
def builder = new groovy.json.JsonBuilder()
builder.x {
person {
firstName 'Guillame'
lastName 'Laforge'
// Named arguments are valid values for objects too
address {
city 'Paris'
country 'France'
zip {
af 'a'
}
}
married true
// a list of values
conferences {a 'JavaOne'} {a 'Gr8conf'}
}
}
println builder.toPrettyString()
assert builder.toPrettyString() == exp
}
JsonSlurper
让我们方便的操纵 json
使用
static void main(String[] args) {
def builder = new JsonBuilder()
builder.x {
person {
firstName 'Guillame'
lastName 'Laforge'
// Named arguments are valid values for objects too
address {
city 'Paris'
country 'France'
zip {
af 'a'
}
}
married true
// a list of values
conferences {a 'JavaOne'} {a 'Gr8conf'}
}
}
def json = builder.toString()
def res = new JsonSlurper().parseText(json)
println res.x.person.conferences[1].a
}
-
Groovy
棒,每天都有实质性输出,加油!
👍