这里主要是用
com.fasterxml.jackson.databind.ObjectMapper 类里面的
@SuppressWarnings("resource")
public String writeValueAsString(Object value) throws JsonProcessingException
例如:
Map<String,String> map = new HashMap<String,String>();
ObjectMapper objectMapper = new ObjectMapper();
map.put("b", "b");
map.put("a", "a");
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
map.put("occurTime", sdf.format(new Date()));
System.out.println("print map: " + map);
String jsonStr = objectMapper.writeValueAsString(map);
System.out.println("print json: " + jsonStr);
这里生成的Json String 如果对字段顺序有要求,那就不能用HashMap了,比如以b,a,occurTime的顺序put到map,结果可能会这样
print map: {occurTime=2018-03-07 09:46:46, b=b, a=a}
print json: {“occurTime”:”2018-03-07 09:46:46”,”b”:”b”,”a”:”a”}
所以Jackson对map的遍历,应该是跟map存储数据的方式有关,那么顺序改变也就很正常了。
看看writeValueAsString这个方法:
protected final void _configAndWriteValue(JsonGenerator g, Object value)
throws IOException
{
SerializationConfig cfg = getSerializationConfig();
cfg.initialize(g); // since 2.5
if (cfg.isEnabled(SerializationFeature.CLOSE_CLOSEABLE) && (value instanceof Closeable)) {
_configAndWriteCloseable(g, value, cfg);
return;
}
try {
_serializerProvider(cfg).serializeValue(g, value);
} catch (Exception e) {
ClassUtil.closeOnFailAndThrowAsIAE(g, e);
return;
}
g.close();
}
里面用到_serializerProvider(cfg).serializeValue(g, value);对对象进行序列化操作,一直跟踪进去:
到了class MapSerializer的
public void serializeFields(Map,?> value, JsonGenerator gen, SerializerProvider provider)
throws IOException
很明显,构造json串时是用entrySet遍历的,所以构造的顺序与遍历map的顺序一致
试试LinkedHashMap:
Map<String,String> map = new LinkedHashMap<String,String>();
{b=b, a=a, occurTime=2018-03-07 09:42:32}
{“b”:”b”,”a”:”a”,”occurTime”:”2018-03-07 09:42:32”}
LinkedHashMap按照put的顺序存储
再试试TreeMap:
Map<String,String> map = new TreeMap<String,String>();
print map: {a=a, b=b, occurTime=2018-03-07 09:46:28}
print json: {“a”:”a”,”b”:”b”,”occurTime”:”2018-03-07 09:46:28”}
TreeMap是有序的,这时构造出来的json也是有序的了。
所以jackson构造map对应的json串,跟map本身存储数据的方式有关,仍然是用entrySet遍历的。