含嵌套数组的JSON解析求助(附Java生成代码与JSON示例)
解决嵌套数组JSON的解析难题
我来帮你搞定这个JSON解析的麻烦事儿!先梳理下你的情况:你用Java从数据库生成了一段带嵌套结构的JSON,但解析的时候碰了不少钉子。先拆解问题根源,再给你针对性的解决方案。
待解析的JSON内容
[ { }, { "Cliente0":[ { "codrefcli":"1541121" }, { "razonsocial":"Perico de los palotes" }, { "cif":"45417265" }, { "num":"964491837" }, { "correo":"perico@yahoo.com" }, { "direccion":"calle maria la vieja" }, { "metodopago":"T" }, { "observaciones":"que pesado" } ] }, { "Empleado0":[ { "codempleado":"1" }, { "nombre":"Carlos" }, { "apellidos":"Basilio" }, { "dni":"15421451H" }, { "direccion":"Calle el rio" }, { "fechaalta":"2018-05-17" }, { "copiacontrato":"aaa" }, { "numcuenta":"884723877" } ] }, { }, { "PedidoCliente0":[ { "numped":"454524" }, { "fechapedido":"2018-05-09" }, { "formapago":"Efectivo" }, { "enviadoa":"Perico de los palotes" }, { "codcliente":"1541121" }, { "cpp":"5132413" } ] }, { "PedidoProveedor0":[ { "numped":"7455112" }, { "fechapedido":"2018-05-01" }, { "formapago":"Efectivo" }, { "enviadoa":"Calle el marino" }, { "codcliente":"10" }, { "cpp":"4555424" } ] }, { "Producto0":[ { "crf":"4555424" }, { "name":"Limpiador" }, { "desc":"Producto de importacion italiano" }, { "pve":"8.44" }, { "pvp":"14.99" }, { "cdp":"10" }, { "familia":"Limpieza" }, { "existencias":"10" } ], "Producto1":[ { "crf":"5132413" }, { "name":"Colador" }, { "desc":"Colador de acero" }, { "pve":"15" }, { "pvp":"18" }, { "cdp":"10" }, { "familia":"Cocina" }, { "existencias":"100" } ] }, { }, { "Proveedor0":[ { "crf":"10" }, { "razonsocial":"pene" }, { "cif":"10" }, { "num":"10" }, { "correo":"10" }, { "direccion":"10" }, { "metodopago":"1" }, { "observaciones":"10" } ], "Proveedor1":[ { "crf":"5421452" }, { "razonsocial":"Falete" }, { "cif":"45411" }, { "num":"42314" }, { "correo":"falete@gmail.com" }, { "direccion":"tu casa" }, { "metodopago":"T" }, { "observaciones":"Es muy pesado" } ] } ]
问题根源分析
你的Java生成代码犯了一个典型的小错误:把同一个实体的每个字段单独封装成一个JSONObject,再塞进数组里。比如一个客户的codrefcli、razonsocial等字段,本该放在同一个对象里,但你却给每个字段新建一个对象,导致生成的JSON里每个客户都是一个数组,数组里全是只有单个键值对的小对象。这种结构不仅冗余,解析起来也格外麻烦。
举个例子,你原来的Clientes部分代码:
while(rs.next()) { JSONArray list2 = new JSONArray(); JSONObject jobja = new JSONObject(); JSONObject jobjb = new JSONObject(); // ... 每个字段都new一个JSONObject jobja.put("codrefcli", b1); jobjb.put("razonsocial", b2); // ... 把所有单字段对象加到数组 list2.add(jobja); list2.add(jobjb); // ... jobjt2.put("Cliente"+i++, list2); }
这就导致了Cliente0是一个数组,里面全是单键对象,完全没必要。
改进的Java生成代码
正确的做法是:把同一个实体的所有字段都放到一个JSONObject里,如果是多个实体,就统一放到JSONArray中。比如修改后的Clientes部分代码:
// Clientes String query2 = "select * from Clientes"; rs = st.executeQuery(query2); JSONArray clientesArray = new JSONArray(); // 用数组存所有客户 i=0; while(rs.next()) { JSONObject clienteObj = new JSONObject(); // 一个客户对应一个对象 String b1 = rs.getString("CodRefCli"); String b2 = rs.getString("RazonSocial"); String b3 = rs.getString("CIF"); String b4 = rs.getString("Num"); String b5 = rs.getString("Correo"); String b6 = rs.getString("Direccion"); String b7 = rs.getString("MetodoPago"); String b8 = rs.getString("Observaciones"); // 所有字段都放到同一个对象里 clienteObj.put("codrefcli", b1); clienteObj.put("razonsocial", b2); clienteObj.put("cif", b3); clienteObj.put("num", b4); clienteObj.put("correo", b5); clienteObj.put("direccion", b6); clienteObj.put("metodopago", b7); clienteObj.put("observaciones", b8); clientesArray.add(clienteObj); // 把客户对象加到数组 // 如果还是要保留原来的命名方式(比如Cliente0、Cliente1),可以替换成: // jobjt2.put("Cliente"+i++, clienteObj); } listt.add(clientesArray); // 或者add(jobjt2),根据你需要的结构选择
其他部分(Empleados、Productos等)都可以按照这个逻辑修改,生成的JSON结构会清晰很多,比如Clientes部分会变成:
[ { "codrefcli":"1541121", "razonsocial":"Perico de los palotes", "cif":"45417265", ... } ]
或者如果你保留Cliente0这样的键,就是:
{ "Cliente0": { "codrefcli":"1541121", "razonsocial":"Perico de los palotes", ... }, "Cliente1": { ... } }
解析JSON的示例代码
情况1:解析改进后的清晰结构(以Clientes数组为例)
用org.json库解析,代码非常直观:
import org.json.JSONArray; import org.json.JSONObject; public class JsonParser { public static void main(String[] args) { String jsonStr = "你的改进后的JSON字符串"; JSONArray mainArray = new JSONArray(jsonStr); // 假设Clientes是mainArray里的第二个元素(索引1) JSONArray clientesArray = mainArray.getJSONArray(1); for (int j = 0; j < clientesArray.length(); j++) { JSONObject cliente = clientesArray.getJSONObject(j); String codrefcli = cliente.getString("codrefcli"); String razonsocial = cliente.getString("razonsocial"); String cif = cliente.getString("cif"); // ... 获取其他字段 System.out.println("客户:" + razonsocial + ",编码:" + codrefcli); } } }
情况2:解析你原来的冗余结构(不推荐,但可以实现)
如果你暂时不想修改生成代码,也可以解析原来的JSON,只是需要遍历数组里的每个单键对象,把它们合并成一个完整的实体:
import org.json.JSONArray; import org.json.JSONObject; public class OldJsonParser { public static void main(String[] args) { String jsonStr = "你原来的JSON字符串"; JSONArray mainArray = new JSONArray(jsonStr); // 获取Cliente0所在的对象(mainArray的索引1) JSONObject clienteWrapper = mainArray.getJSONObject(1); JSONArray clienteFieldsArray = clienteWrapper.getJSONArray("Cliente0"); // 合并成一个完整的客户对象 JSONObject cliente = new JSONObject(); for (int j = 0; j < clienteFieldsArray.length(); j++) { JSONObject fieldObj = clienteFieldsArray.getJSONObject(j); // 每个fieldObj只有一个键值对,遍历取出键 String key = fieldObj.keys().next(); Object value = fieldObj.get(key); cliente.put(key, value); } // 现在可以正常获取字段了 System.out.println("客户名称:" + cliente.getString("razonsocial")); System.out.println("客户编码:" + cliente.getString("codrefcli")); } }
总结
优先推荐改进Java生成代码,生成结构清晰的JSON,这样解析会非常简单,也符合JSON的最佳实践。如果必须解析原来的冗余结构,就用第二种方法合并字段对象。
内容的提问来源于stack exchange,提问作者Gyswus
相关产品推荐
相关产品推荐

