JSON扁平化工具仅返回users数组最后一个对象,求排查与修改方案
问题:JSON扁平化工具仅返回数组中最后一个用户的结果
我有一个包含多个用户的JSON结构,想通过Java代码将其扁平化,但遇到了一个问题:不管数组里有多少用户,代码始终只输出最后一个用户的扁平化结果。
输入JSON结构
{ "users": [ { "displayName": "Sharad Dutta", "givenName": "", "surname": "", "extension_user_type": "user", "identities": [ { "signInType": "emailAddress", "issuerAssignedId": "kkr007@gmail.com" } ], "extension_timezone": "VET", "extension_locale": "en-GB", "extension_tenant": "EG12345" }, { "displayName": "Sharad Dutta", "givenName": "", "surname": "", "extension_user_type": "user", "identities": [ { "signInType": "emailAddress", "issuerAssignedId": "kkr007@gmail.com" } ], "extension_timezone": "VET", "extension_locale": "en-GB", "extension_tenant": "EG12345" } ] }
期望的扁平化输出(示例)
{ "extension_timezone": "VET", "extension_tenant": "EG12345", "extension_locale": "en-GB", "signInType": "userName", "displayName": "Wayne Rooney", "surname": "Rooney", "givenName": "Wayne", "issuerAssignedId": "pdhongade007", "extension_user_type": "user" }
问题代码
public class TestConvertor { static String userJsonAsString; public static void main(String[] args) throws JSONException { String userJsonFile = "C:\\Users\\Administrator\\Desktop\\jsonRes\\json_format_user_data_input_file.json"; try { userJsonAsString = readFileAsAString(userJsonFile); } catch (Exception e1) { e1.printStackTrace(); } JSONObject object = new JSONObject(userJsonAsString); // this is your input Map<String, Object> flatKeyValue = new HashMap<String, Object>(); System.out.println("flatKeyValue : " + flatKeyValue); readValues(object, flatKeyValue); System.out.println(new JSONObject(flatKeyValue)); // this is flat } static void readValues(JSONObject object, Map<String, Object> json) throws JSONException { for (Iterator it = object.keys(); it.hasNext(); ) { String key = (String) it.next(); Object next = object.get(key); readValue(json, key, next); } } static void readValue(Map<String, Object> json, String key, Object next) throws JSONException { if (next instanceof JSONArray) { JSONArray array = (JSONArray) next; for (int i = 0; i < array.length(); ++i) { readValue(json, key, array.opt(i)); } } else if (next instanceof JSONObject) { readValues((JSONObject) next, json); } else { json.put(key, next); } } private static String readFileAsAString(String inputJsonFile) throws Exception { return new String(Files.readAllBytes(Paths.get(inputJsonFile))); } }
问题原因分析
核心问题出在共享同一个Map对象处理数组中的所有元素。当遍历users数组时,每一个用户对象的扁平化键值对都会往同一个flatKeyValue Map里存,后面用户的键值对会直接覆盖前面用户的同名键(比如两个用户都有displayName,第二个的会覆盖第一个的),最后Map里就只剩下最后一个用户的所有键值对了。
另外,你的代码没有考虑数组元素的区分——如果要保留所有用户的扁平化结果,应该把每个用户的扁平化Map放到一个集合(比如List)里,而不是用单个Map来存储。
修改建议与修正代码
我们需要调整逻辑:当遇到users数组时,为每个用户创建独立的扁平化Map,然后把这些Map收集到一个List中,最终输出这个List的JSON(或者根据需求选择输出所有用户,还是允许用户指定索引)。
修正后的代码如下:
import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; import java.nio.file.Files; import java.nio.file.Paths; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; public class TestConvertor { static String userJsonAsString; public static void main(String[] args) throws JSONException { String userJsonFile = "C:\\Users\\Administrator\\Desktop\\jsonRes\\json_format_user_data_input_file.json"; try { userJsonAsString = readFileAsAString(userJsonFile); } catch (Exception e1) { e1.printStackTrace(); } JSONObject object = new JSONObject(userJsonAsString); // 输入JSON List<Map<String, Object>> allFlatUsers = new ArrayList<>(); // 处理users数组 JSONArray usersArray = object.getJSONArray("users"); for (int i = 0; i < usersArray.length(); i++) { JSONObject userObj = usersArray.getJSONObject(i); Map<String, Object> flatUser = new HashMap<>(); readValues(userObj, flatUser); allFlatUsers.add(flatUser); } // 输出所有扁平化后的用户 System.out.println(new JSONArray(allFlatUsers)); // 如果只需要第一个用户,直接取allFlatUsers.get(0)即可 // System.out.println(new JSONObject(allFlatUsers.get(0))); } static void readValues(JSONObject object, Map<String, Object> json) throws JSONException { for (Iterator it = object.keys(); it.hasNext(); ) { String key = (String) it.next(); Object next = object.get(key); readValue(json, key, next); } } static void readValue(Map<String, Object> json, String key, Object next) throws JSONException { if (next instanceof JSONArray) { JSONArray array = (JSONArray) next; // 处理内部数组(比如identities),这里直接遍历每个元素并扁平化 for (int i = 0; i < array.length(); ++i) { readValue(json, key, array.opt(i)); } } else if (next instanceof JSONObject) { readValues((JSONObject) next, json); } else { json.put(key, next); } } private static String readFileAsAString(String inputJsonFile) throws Exception { return new String(Files.readAllBytes(Paths.get(inputJsonFile))); } }
代码说明
- 独立处理每个用户:遍历
users数组时,为每个用户创建新的HashMap,避免键值对覆盖。 - 收集所有结果:用
List<Map<String, Object>>存储所有用户的扁平化结果,最终可以输出为JSON数组。 - 保留原有扁平化逻辑:内部的
readValues和readValue方法保持不变,继续处理单个用户对象的嵌套结构(比如identities数组)。
如果你只需要输出某个特定用户(比如第一个),直接从allFlatUsers中取出对应索引的Map即可。
内容的提问来源于stack exchange,提问作者horizon
相关产品推荐
相关产品推荐

