有些場景下,在實現一些基礎服務和攔截器的時候,我們可能需要在不知道JSON字符串所屬對象類型的情況下,對JSON字符串中的某些屬性進行遍歷和修改,比如,設置或查詢一些報文頭字段。
在jackson中,使用最多的JsonNode抽象類並沒有提供修改節點值的方法,而是在ObjectNode節點中提供修改接口,這個節點在官方的說明中,一般用於創建新的節點。
假設packet.getDecryptRequestBody()中是一個json字符串,可以通過如下代碼查看
JsonNode rootNode = mapper.readTree(packet.getDecryptRequestBody()); JsonNode targetNode = null; targetNode = rootNode.findValue("rpcMsgId"); // 查找第一級的rpcMsgId屬性,如果屬性不存在,則返回null,屬性值如果為明確的null,返回NullNode,否則返回正常的JsonNode // 注:JsonNode還提供了find/path/get等獲取節點的方法,但是這三種方法都不能明確的區分節點不存在、為明確的null。所以,應該使用findValue方法。
如果只是純粹的遍歷和類似JsonTree的構造,網上各種文章一堆,主要是對原json中屬性的修改。可通過如下方式進行修改:
((ObjectNode)targetNode).put("rpcMsgId","abcdefg1234567890"); // 通過強制轉換為ObjectNode,就可以對當前節點進行修改,其他的XXXNode均沒有提供相關的API接口 String modifiedJsonStr = mapper.writeValueAsString(rootNode); // 最后重新生成json字符串,這跟dom4j修改xml一樣,只能重新生成,內置不支持直接修改原文件
完整的例子如下:
public class PacketHead { private String serviceId; private String rpcMsgId;private Map<String,String> spiderOpts; //此處getter/setter省去 } public class SpiderRequest { private PacketHead spiderPacketHead; private String requestBody; private String resultInfo; public SpiderPacketHead getSpiderPacketHead() { return spiderPacketHead; } public void setSpiderPacketHead(SpiderPacketHead spiderPacketHead) { this.spiderPacketHead = spiderPacketHead; } public String getRequestBody() { return requestBody; } public void setRequestBody(String requestBody) { this.requestBody = requestBody; } @JsonIgnore public String getRequestId() { return spiderPacketHead.getRpcMsgId(); } public String getResultInfo() { return resultInfo; } public void setResultInfo(String resultInfo) { this.resultInfo = resultInfo; } public static void main(String[] args) throws JsonProcessingException, IOException { SpiderRequest req = new SpiderRequest(); req.setSpiderPacketHead(new SpiderPacketHead()); String json = JsonUtils.toJson(req); System.out.println(json); JsonNode node = mapper.readTree(json); JsonNode node1 = node.findValue("spiderPacketHead"); ObjectNode node2 = (ObjectNode) node1; node2.put("rpcMsgId", "abc"); System.out.println(mapper.writeValueAsString(node)); }
