Skip to content
核心力量 edited this page May 9, 2013 · 1 revision

使用JSAN

JSAN 是JavaScript Array Notation的缩写,用轻量级的文本形式描述数组的结构与取值。
一个最典型的JSAN文本类似于[“1”,2,“three”,true]
JSAN在Java中的实现继承了Iterable接口,并且可以解析/生成JSAN文本。

代码范例

如果字符串变量String str的值为[“1”,2,“three”,true],可以通过(JSAN)JSON.Parse(CharSequence)方法来解析该字符串,以得到JSAN对象。

// 解析JSAN文本
JSAN jsan = (JSAN) JSON.Parse(str);

通过调用JSAN对象的toString()方法,可以将JSAN对象还原成JSAN文本。

// 输出JSAN文本["1",2,"three",true]
System.out.println("输出JSAN文本:" + jsan.toString());

如果想格式化JSAN文本,则可以调用toString(int)方法,其参数表示缩进字符的个数,通常指定为0。

/* 以0缩进字符输出JSAN文本
[
    "1",
    2,
    "three",
    true
]
*/
System.out.println("格式化输出文本:" + jsan.toString(0));

JSAN对象延续了JSON中的attr(String)方法,用以读取某个键对应的属性值(类似于Map的get方法)。

System.out.println("读取id属性:" + jsan.attr("id"));

此外,JSAN对象还可以直接根据非负整数下标读取其中的元素。

System.out.println("读取第0个元素:" + jsan.attr(0));

这里并不一定强制要求传入的参数为int,亦可以是表示非负整数的字符串。

System.out.println("读取第0个元素:" + jsan.attr("0"));

与JSON类似,设置属性的方法则为attr(String,Object),第一个参数为键名,第二个为属性值。

json.attr("id", 2);
System.out.println("设置id属性后:" + json.attr("id"));

JSAN对象还可以对非负整数下标设置对应的元素。

jsan.attr(0, "zero");

jsan.attr("0", "zero");

需要注意的是,虽然JSAN与JSON一样,可以将任何普通的字符串作为键,但是非负整数(字符串)键会始终依次存放在普通字符串键之前。如下面的例子中,虽然"strKey"先于"4"设置,但实际存放的结果是,4被存放在JSAN段,并先于strKey被遍历。

System.out.println("不同种类键的顺序:");
jsan.attr("strKey", "Stored as JSON");
jsan.attr("4", "Later set but position before strKey");
for (Pair pair : jsan.pairs())
{
	System.out.println(pair.getKey() + " => " + pair.getValue());
}

对非负整数下标对应的元素可以用splice方法对数组元素进行删减、扩充。

System.out.println("用0个元素在位置1处填充2个位置的元素" + jsan.splice(1, 2));
System.out.println("用3个元素在位置1处填充0个位置的元素" + jsan.splice(1, 0, "hey!", 2, false));

attr(String,Object)、attr(int,Object)方法同样支持链式调用。

System.out.println("链式调用attr方法:" + jsan.attr("id", 3).attr(1, "Quene").toString(0));

JSAN会将(任意多维)数组对象换换成JSAN对象。

int[][] arr = new int[][] { { 1, 2, 3 }, { 2, 3, 4 }, { 3, 4, 5 } };
jsan.add(arr);
System.out.println("添加数组元素后:" + jsan.toString());

通过val系列方法读取JSAN元素时可以指定默认值。

System.out.println("以整型读取第5个元素时指定默认值:" + jsan.valInteger(5, 4));

由于JSAN实现了Iterable接口,因此可以按下面的方式遍历其中所有元素。

System.out.println("遍历JSAN中的所有元素:");
for (Object value : jsan)
{
	System.out.println(value);
}

JSAN可以通过反射特性读取POJO,POJO中所有通过getter开放的属性都可以被读取。
假如有下面的POJO类

public class DemoPOJO
{
	private int				id;
	private String				name;
	private double				value;
	private Map<String, Object>		dict;
	private float				income;

	public DemoPOJO()
	{
		this.id = 1;
		this.name = "Joke";
		this.value = 1.23;
		this.dict = new LinkedHashMap<String, Object>();
		this.dict.put("one", 1);
		this.dict.put("two", 2);
		this.income = 100.1f;
	}

	// JSAN在反射时,会将Map类对象反射为JSAN。
	public Map<String, Object> getDict()
	{
		return dict;
	}

	public int getId()
	{
		return id;
	}

	// 不开放此属性,JSAN将不会反射该数据。
	protected float getIncome()
	{
		return income;
	}

	public String getName()
	{
		return name;
	}

	public double getValue()
	{
		return value;
	}
}
DemoPOJO pojo = new DemoPOJO();

JSAN反射对象,默认反射所有字段,并以非负整数下标存放。

DemoPOJO pojo = new DemoPOJO();
jsan.clean().reflect(pojo);
System.out.println("反射读取pojo:" + jsan.toString());

JSAN反射对象中的部分属性。

jsan.clean().reflect(pojo, "id", "name", "value");
System.out.println("反射部分属性:" + jsan.toString());

对反射部分属性并进行映射转换

Map<String, Object> templateMap = new LinkedHashMap<String, Object>();
templateMap.put("2", "id");
templateMap.put("0", "name");
templateMap.put("1", "value");
jsan.clean().reflect(pojo, templateMap);
System.out.println("反射部分属性并映射转换:");
for (Pair pair : jsan.pairs())
{
	System.out.println(pair.getKey() + " => " + pair.getValue());
}
Clone this wiki locally