如何区分JsonObject中数值数组与对象数组类型属性?
问题
如何区分“MonthQuota”和“Forecast”属性?在实际程序中,我使用JsonObject类和动态ProDataSet进行递归解析,请给出适配该场景的解决方案。
我需要解析的JSON中,“MonthQuota”是数值数组,“Forecast”是对象数组,示例JSON如下:
{ "ttSalesRep": [ { "SalesRep": "BBB", "RepName": "Brawn, Bubba B.", "Region": "East", "MonthQuota": [ 1600,1648,1697,1748,1800,1854 ], "Forecast": [ { "Month1": "Enero", "Amount1": 111.1 }, { "Month1": "Marzo", "Amount1": 111.2 } ] } ] }
注:原示例中“Forcast”“Amont1”为拼写错误,已修正为“Forecast”“Amount1”
由于需要以不同方式解析这两个属性,我尝试使用GetType方法,但“MonthQuota”和“Forecast”的GetType返回值均为5,无法区分。以下是复现问题的示例代码:
DEFINE VARIABLE myParser AS ObjectModelParser NO-UNDO. DEFINE VARIABLE myConstruct AS JsonConstruct NO-UNDO. DEFINE VARIABLE myJsonObj AS JsonObject NO-UNDO. DEFINE VARIABLE myArray AS CHAR EXTENT NO-UNDO. DEFINE VARIABLE my_JSON_File AS CHARACTER NO-UNDO. my_JSON_File = "myJsonFile.json". myParser = NEW ObjectModelParser(). myConstruct = myParser:ParseFile(my_JSON_File). myJsonObj = CAST(myConstruct, JsonObject). myArray = myJsonObj:GetJsonArray("ttSalesRep"):GetJsonObject(1):GetNames(). MESSAGE myArray[4] "=" myJsonObj:GetJsonArray("ttSalesRep"):GetJsonObject(1):GetType(myArray[4]) SKIP myArray[5] "=" myJsonObj:GetJsonArray("ttSalesRep"):GetJsonObject(1):GetType(myArray[5]) SKIP VIEW-AS ALERT-BOX.
解决方案
方法1:通过数组元素的类型区分
GetType()返回5表示两者都是JsonArray类型,无法直接区分,但可以读取数组首个元素的类型判断:
- 数值数组的元素类型为3(JsonNumber)
- 对象数组的元素类型为4(JsonObject)
示例代码:
DEFINE VARIABLE salesRepObj AS JsonObject NO-UNDO. DEFINE VARIABLE quotaArray AS JsonArray NO-UNDO. DEFINE VARIABLE forecastArray AS JsonArray NO-UNDO. salesRepObj = myJsonObj:GetJsonArray("ttSalesRep"):GetJsonObject(1). // 处理MonthQuota数值数组 quotaArray = salesRepObj:GetJsonArray("MonthQuota"). IF quotaArray:GetType(1) = 3 THEN DO: DEFINE VARIABLE i AS INTEGER NO-UNDO. DEFINE VARIABLE quotaVal AS DECIMAL NO-UNDO. DO i = 1 TO quotaArray:Count(): quotaVal = quotaArray:GetJsonNumber(i):DecimalValue. // 将quotaVal写入动态ProDataSet对应字段 END. END. // 处理Forecast对象数组 forecastArray = salesRepObj:GetJsonArray("Forecast"). IF forecastArray:GetType(1) = 4 THEN DO: DEFINE VARIABLE i AS INTEGER NO-UNDO. DEFINE VARIABLE forecastObj AS JsonObject NO-UNDO. DO i = 1 TO forecastArray:Count(): forecastObj = forecastArray:GetJsonObject(i). DEFINE VARIABLE monthName AS CHARACTER NO-UNDO. DEFINE VARIABLE amount AS DECIMAL NO-UNDO. monthName = forecastObj:GetJsonString("Month1"):Value. amount = forecastObj:GetJsonNumber("Amount1"):DecimalValue. // 将monthName和amount写入动态ProDataSet子表 END. END.
方法2:结合属性名称预判(适用于固定结构场景)
如果JSON结构固定,可直接通过属性名称指定解析逻辑:
- 遇到
MonthQuota按数值数组解析 - 遇到
Forecast按对象数组解析
递归解析时的示例逻辑:
PROCEDURE ProcessJsonObject: DEFINE INPUT PARAMETER pJsonObj AS JsonObject NO-UNDO. DEFINE INPUT PARAMETER pDataSet AS HANDLE NO-UNDO. DEFINE INPUT PARAMETER pBuffer AS HANDLE NO-UNDO. DEFINE VARIABLE names AS CHARACTER EXTENT NO-UNDO. DEFINE VARIABLE i AS INTEGER NO-UNDO. DEFINE VARIABLE propName AS CHARACTER NO-UNDO. names = pJsonObj:GetNames(). DO i = 1 TO EXTENT(names): propName = names[i]. CASE propName: WHEN "MonthQuota": // 数值数组解析逻辑 DEFINE VARIABLE arr AS JsonArray NO-UNDO. arr = pJsonObj:GetJsonArray(propName). // 写入动态ProDataSet对应字段 WHEN "Forecast": // 对象数组解析逻辑 DEFINE VARIABLE arr AS JsonArray NO-UNDO. arr = pJsonObj:GetJsonArray(propName). // 创建动态ProDataSet子表行并写入属性值 OTHERWISE: // 普通属性解析 CASE pJsonObj:GetType(propName): WHEN 2: // JsonString pBuffer:BUFFER-FIELD(propName):VALUE = pJsonObj:GetJsonString(propName):Value. WHEN 3: // JsonNumber pBuffer:BUFFER-FIELD(propName):VALUE = pJsonObj:GetJsonNumber(propName):DecimalValue. // 其他类型处理 END CASE. END CASE. END. END PROCEDURE.
方法3:通过类型转换异常判断(适配空数组场景)
如果数组可能为空,可尝试将元素转换为JsonObject,失败则判定为数值数组:
DEFINE VARIABLE arr AS JsonArray NO-UNDO. DEFINE VARIABLE isObjectArray AS LOGICAL NO-UNDO. arr = salesRepObj:GetJsonArray(propName). isObjectArray = FALSE. IF arr:Count() > 0 THEN DO: DO ON ERROR UNDO, LEAVE: CAST(arr:GetJsonConstruct(1), JsonObject). isObjectArray = TRUE. END. END. IF isObjectArray THEN DO: // 对象数组处理逻辑 END ELSE DO: // 数值数组处理逻辑 END.
内容的提问来源于stack exchange,提问作者SSosa
相关产品推荐
相关产品推荐

