如何修改JSON取值函数以获取嵌套JSON对象中的字段值?
如何修改JSON解析函数支持嵌套字段取值?
我来帮你搞定这个嵌套JSON的解析问题~先理清楚你的场景:原来的函数能处理普通字段、数字数组,但现在新增了NEWVALUE这个嵌套JSON对象,需要单独获取它内部的canStartNewValue1和canStartroupValue的值,下面给你两种实用的解决方案:
方案一:支持点分隔的字段路径(推荐,灵活度高)
这种方式允许你把字段名写成类似NEWVALUE.canStartNewValue1的路径格式,函数会自动逐层解析嵌套对象。我们先重构原函数,把类型处理逻辑抽离出来复用,再增加路径解析的逻辑:
private Object getValueForField(Field field) { try { JSONObject currentConfig = runtimeConfiguration; // 将字段路径拆分成层级数组,比如"NEWVALUE.canStartNewValue1"拆分为["NEWVALUE", "canStartNewValue1"] String[] fieldPathSegments = field.fieldName.split("\\."); for (int i = 0; i < fieldPathSegments.length; i++) { String currentKey = fieldPathSegments[i]; // 如果当前层级不存在该字段,或者不允许从服务器更新,直接返回默认值 if (!currentConfig.has(currentKey) || !field.updateFromServer) { return field.defaultValue; } Object currentValue = currentConfig.get(currentKey); // 如果不是最后一级路径,需要确保当前值是JSON对象,否则返回默认值 if (i < fieldPathSegments.length - 1) { if (!(currentValue instanceof JSONObject)) { return field.defaultValue; } currentConfig = (JSONObject) currentValue; } else { // 到了最后一级,处理值的类型(复用原来的逻辑) return processValue(currentValue); } } } catch (Exception e) { e.printStackTrace(); } return field.defaultValue; } // 抽离原有的值类型处理逻辑,让代码更清晰且可复用 private Object processValue(Object value) { if (value instanceof JSONArray) { JSONArray values = (JSONArray) value; if (values.get(0) instanceof Number) { long[] retVals = new long[values.length()]; for (int i = 0; i < values.length(); i++) { retVals[i] = ((Number) values.get(i)).longValue(); } return retVals; } // 如果数组不是数字类型,直接返回原JSONArray return values; } else if (value instanceof Number) { return ((Number) value).longValue(); } else { // 布尔、字符串等类型直接返回原值 return value; } }
使用时,你只需要给Field的fieldName设置成路径格式就行:
- 要取
canStartNewValue1,就把field.fieldName设为NEWVALUE.canStartNewValue1 - 原来的普通字段比如
forceDeviceLockout保持不变,完全兼容原有逻辑
方案二:给Field类新增父字段属性(适合嵌套层级少的场景)
如果不想修改字段名的格式,可以给你的Field类加一个parentObjectField属性,用来指定当前字段所属的嵌套对象名:
// 假设你的Field类原来的结构,新增parentObjectField属性 class Field { String fieldName; boolean updateFromServer; Object defaultValue; String parentObjectField; // 新增:比如要取NEWVALUE里的字段,这里就设为"NEWVALUE" }
然后修改解析函数,先定位到父对象,再取目标字段:
private Object getValueForField(Field field) { try { JSONObject currentConfig = runtimeConfiguration; // 如果有指定父对象字段,先定位到嵌套的JSON对象 if (field.parentObjectField != null && !field.parentObjectField.isEmpty()) { if (!currentConfig.has(field.parentObjectField) || !field.updateFromServer) { return field.defaultValue; } Object parentValue = currentConfig.get(field.parentObjectField); // 父字段必须是JSON对象,否则返回默认值 if (!(parentValue instanceof JSONObject)) { return field.defaultValue; } currentConfig = (JSONObject) parentValue; } // 接下来处理目标字段,逻辑和原来基本一致 if (!currentConfig.has(field.fieldName) || !field.updateFromServer) { return field.defaultValue; } Object value = currentConfig.get(field.fieldName); return processValue(value); } catch (Exception e) { e.printStackTrace(); } return field.defaultValue; } // 同样复用这个值类型处理方法 private Object processValue(Object value) { if (value instanceof JSONArray) { JSONArray values = (JSONArray) value; if (values.get(0) instanceof Number) { long[] retVals = new long[values.length()]; for (int i = 0; i < values.length(); i++) { retVals[i] = ((Number) values.get(i)).longValue(); } return retVals; } return values; } else if (value instanceof Number) { return ((Number) value).longValue(); } else { return value; } }
使用时,比如要取canStartNewValue1,就把Field的parentObjectField设为NEWVALUE,fieldName设为canStartNewValue1即可。
这两种方案都能完美兼容你原来的解析逻辑,选哪种就看你的实际场景啦~
内容的提问来源于stack exchange,提问作者user2386226
相关产品推荐
相关产品推荐

