Jackson第二篇【從JSON字符串中取值】

     第一篇咱們主要學習了實體與json的相互轉換的問題,但是咱們需要的是數據 你轉換18遍我取不到數據也是扯淡,那麼今天咱們就一起學習一下如何從使用Jackson從Json字符串中取值。廢話不說直接上代碼(注意第一篇裏面的方法我都移到JsonProcessUtil裏面了方便使用 )。

    從Json字符串中取出指定節點的值

 

	public static void getValue(TestVo vo) throws Exception {
		// 準備工作 傳入vo請參照第一篇裏面的實體。此處不再重新貼上代碼 浪費大家時間
		ObjectMapper mapper = JsonProcessUtil.getMapperInstance(false);
		String voJson = JsonProcessUtil.toJson(vo);
		JsonNode node = mapper.readTree(voJson);// 這裏的JsonNode和XML裏面的Node很像
		System.out.println("readValueFromJson>>>" + node.get("voName").toString());// 獲取voName
		// 輸出結果:readValueFromJson>>>一個容器而已
	}

    怎麼樣簡單吧,但是這個作用不是很大啊!我想獲取TestVo下面的Person的name的值 該怎麼辦呢?彆着急,咱們走起!

 

	public static void getValue(TestVo vo) throws Exception {
		// 準備工作 傳入vo請參照第一篇裏面的實體。此處不再重新貼上代碼 浪費大家時間
		ObjectMapper mapper = JsonProcessUtil.getMapperInstance(false);
		String voJson = JsonProcessUtil.toJson(vo);
		JsonNode node = mapper.readTree(voJson);// 這裏的JsonNode和XML裏面的Node很像
		node = node.get("pers");
		System.out.println("node是不是個集合:" + node.isArray());// 這個方法咱們後面會用到先讓它給大家照個面
		for (int i = 0; i < node.size(); i++) {
			JsonNode childNode = node.get(i);
			System.out.println("readValueFromJson>>>" + childNode.get("name").toString());// 獲取name
		}
		/*
		 * 輸出結果 
		 * node是不是個集合:true
		 * readValueFromJson>>>張三 
		 * readValueFromJson>>>李四
		 * readValueFromJson>>>王二麻子
		 */
	}

 怎麼樣功能還行吧?如果這樣你就滿意了,那你也太容易滿足了。現在我在項目中需要像xpath那樣來查找某節點的值(不太瞭解xpath的童鞋彆着急我以後會和大家一起學習下)。/a/b/c/d 這樣找到某個節點的值。爲了增加複雜度,我又給Person類裏面增加 一個List<Person> childs;表示這個人的孩子那麼咱們一往下需找的節點就多了……

  首先看下我準備的數據

 

{"voName":"一個容器而已","pers":[{"name":"張三","age":46,"childs":[{"name":"小張三1","age":20,"childs":null},{"name":"小張三2","age":17,"childs":null}]},{"name":"李四","age":29,"childs":[{"name":"小李四1","age":20,"childs":null}]},{"name":"王二麻子","age":23,"childs":null}]}

  張三:有兩個孩子  李四:有一個孩子  王二麻子:沒有孩子

  我現在要做的就是把所有的孩子找出來。

  廢話不多說直接看代碼

 

	public static void main(String[] args) throws Exception {
		// 準備數據
		List<Person> pers = new ArrayList<Person>();
		List<Person> childs = new ArrayList<Person>();
		Person p = new Person("張三", 46);
		childs.add(new Person("小張三1", 20));
		childs.add(new Person("小張三2", 17));
		p.setChilds(childs);
		pers.add(p);
		p = new Person("李四", 29);
		childs = new ArrayList<Person>();
		childs.add(new Person("小李四1", 20));
		p.setChilds(childs);
		pers.add(p);
		p = new Person("王二麻子", 23);
		pers.add(p);
		TestVo vo = new TestVo("一個容器而已", pers);
		// 實體轉JSON字符串
		String json = beanToJson(vo);
		Object[] obj = readValueFromJson(json, "pers:childs:name").toArray();
		System.out.println(Arrays.toString(obj));
		// 輸出結果:[小張三1, 小張三2, 小李四1]
	}

    好玩吧,接下來咱們就一起看下我這個readValueFormJson是如何實現的呢?

 

	/**
	 * 從json中讀取tagPath處的值 tagPath用 :分隔
	 * 
	 * @param json
	 * @param tagPath
	 * @return
	 * @throws Exception
	 */
	public static List<String> readValueFromJson(String json, String tagPath) throws Exception {
		// 返回值
		List<String> value = new ArrayList<String>();
		if (CommonUtil.isEmpty(json) || (CommonUtil.isEmpty(tagPath))) {
			return value;
		}
		ObjectMapper mapper = CommonUtil.getMapperInstance(false);
		String[] path = tagPath.split(":");
		JsonNode node = mapper.readTree(json);
		getJsonValue(node, path, value, 1);
		return value;
	}

	public static void getJsonValue(JsonNode node, String[] path, List<String> values, int nextIndex) {
		if (CommonUtil.isEmpty(node)) {
			return;
		}
		// 是路徑的最後就直接取值
		if (nextIndex == path.length) {
			if (node.isArray()) {
				for (int i = 0; i < node.size(); i++) {
					JsonNode child = node.get(i).get(path[nextIndex - 1]);
					if (CommonUtil.isEmpty(child)) {
						continue;
					}
					values.add(child.toString());
				}
			} else {
				JsonNode child = node.get(path[nextIndex - 1]);
				if (!CommonUtil.isEmpty(child)) {
					values.add(child.toString);
				}
			}
			return;
		}
		// 判斷是Node下是集合還是一個節點
		node = node.get(path[nextIndex - 1]);
		if (node.isArray()) {
			for (int i = 0; i < node.size(); i++) {
				getJsonValue(node.get(i), path, values, nextIndex + 1);
			}
		} else {
			getJsonValue(node, path, values, nextIndex + 1);
		}
	}

     挺好吧,功能雖然實現了。但是童鞋們可能會對這個產生疑問,你他X的不是脫褲子放屁嗎?先把Bean轉換成Json再從Json中取值。效率低不說,而且還複雜。我直接通過get方法多好……如果你這樣想了說明你是一個思考者!但是有種情況(本人在開發中遇到的)如果這個bean非常大 不同情況你需要的字段是不一樣的 那你怎辦? 根據情況判斷if else if else if?如果有一百種情況呢?那不就累死了。所以在數據庫裏面配置不同業務情況從不同字段取值比較好,這樣就會用到這種功能。另外附上:CommonUtil.isEmpty()方法

/**
	 * 判斷對象是否爲空
	 * 
	 * @param obj
	 * @return
	 */
	public static boolean isEmpty(Object obj) {
		boolean result = true;
		if (obj == null) {
			return true;
		}
		if (obj instanceof String) {
			result = (obj.toString().trim().length() == 0) || obj.toString().trim().equals("null");
		} else if (obj instanceof Collection) {
			result = ((Collection) obj).size() == 0;
		} else {
			result = ((obj == null) || (obj.toString().trim().length() < 1)) ? true : false;
		}
		return result;
	}

 注意:JsonNode 提供了很多種取值的方法,但是爲了通用我選擇了toString()因爲getTextValue(),getIntValue()……一些方法只能返回指定類型的值,這樣不能達到通用。而且有一種情況如果我想要的是整個節點下面所有子節點的值呢?如果使用上面的方法就沒辦法了,只能使用toString()這時候它返回的是整個json字符串。注意:toString()方法如果只返回某一個屬性的值 如:name  而不是一整個大節點如:name,age,gender,那麼它會在返回的字符串上加雙引號,用的時候注意去掉開始結束的雙引號。

今天就學習到這,下篇文章我將與大家一起探討一下爲什麼 我創建一個ObjectMapper對象要搞的那麼複雜!不直接new。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章