Json 空数据行为异常

Posted

技术标签:

【中文标题】Json 空数据行为异常【英文标题】:Json null data behaving strangely 【发布时间】:2016-07-12 09:31:45 【问题描述】:

我在开发中使用 grails 2.3.3,但在处理从 json 网页获取的二维数组时遇到问题。当二维数组的第 3 列中存在空值时,就会出现特定问题。

以下是 grails 中工作流程的概述:

首先渲染json对象:

    render ( ['P' : jsonObject.picId, 'A' : jsonObject.audioId, 'C' : jsonObject.caption, 'V' : jsonObject.vidTemplateId ] as JSON)

然后将其重铸成二维数组以传入 storeVideoSlotData 服务:

def vidpNmList = [][]
vidpNmList[0] = jsonObject.picId
vidpNmList[1] = jsonObject.audioId
vidpNmList[2] = jsonObject.caption

然后调用传递 vidpNmList 的服务:

def vsaInst = vdSlotService.storeVideoSlotData( vidpNmList, session)

在服务中,它再次被重铸成三个独立的组件:

def picId = vidpNmList[0]
def audioId = vidpNmList[1]
def caption = vidpNmList[2]

以下是两种数据形式的列表:

vidpNmList: [[331, 332, 334, null, null, null, null, null, null, null, null, null], [null, null, null, null, null, null, null, null, null , null, null, null], [null, 输入字幕数据, 输入字幕数据, null, null, null, null, null, null, null, null]]

picId: [331, 332, 334, null, null, null, null, null, null, null, null, null]

audioId:[null,null,null,null,null,null,null,null,null,null,null,null]

字幕:[null,输入字幕数据,输入字幕数据,null,null,null,null,null,null,null,null]

在此服务中,对该标题列中包含空值的特定值的任何引用都会导致错误:

当 caption[currSlotNo] 为空值时,此行会导致错误:

if(!(caption[currSlotNo]) ) 
    log.debug(" caption is null and cannot be displayed. ")

错误是:

homevu1.VdSlotService updVideoSlotData pictureInst : 331 picId[currSlotNo]: 331 homevu1.VdSlotService updVideoSlotData picMK: 331

homevu1.VdSlotService updVideoSlotData audMK: null

处理请求时发生errors.GrailsExceptionResolver JSONException:[POST] /HomeVu1/videoShr/getJsVidCoords

JSONArray[0] not found.. Stacktrace 如下: org.codehaus.groovy.grails.web.json.JSONException: JSONArray[0] not found.

如果我引用 vidpNmList 数组中元素的值,也会出现同样的错误。

我做错了什么或者可能有一些解决方法?

这是我引入的一种解决方法,其中包含“try/catch”构造,其中“captionVal”为空:

        def captionVal = null
        try captionVal = caption[currSlotNo] 

            log.debug(" $functionName caption value assigned correctly ")
        
        catch (Exception eWrite)
               
            //      fails - can only trap and work around the error atm.
                log.debug(" $functionName caption value fails to assign correctly - remains at null default - Error Message: $eWrite")                                
        

显示在将 json 对象标题元素从“null”字符串分配给 vidpNmList 之前将其重置为实际 null 的代码:

        for (def iC = 0; iC < jsonObject.caption.size() ; iC++)
        
            String currCap = jsonObject.caption[iC]
            if( currCap == "null") 
            
                log.debug(" getJsVisCoords null value iC: $iC " + " caption[iC]: " + jsonObject.caption[iC] + " currCap Length: " + currCap.length())
                jsonObject.caption[iC] = null
            
            else
            
                log.debug(" getJsVisCoords Non null value iC: $iC " + " caption[iC]: " + jsonObject.caption[iC] + " currCap Length: " + currCap.length())
            

        
        vidpNmList[2] = jsonObject.caption

-麦克

【问题讨论】:

我认为该错误消息根本与 log.debug 行无关。它们看起来像不同的原木。实际消息甚至不在该消息中。 groovy 中的 JSON 对象可能难以捕获空值。我会尝试检查 if (JSONObject.NULL.equals(i.fieldName) i.fieldName=null 。其中 i 是您的迭代 fieldName 在您的情况下将是 catual 索引,即 [indexId] 然后设置 i[indexId]= null 从 JSON 空值中将其设置为真正的常规空值 @vahid 我已经更正了错误日志以匹配数据 - 解释一下,当我运行各种版本的数据时,我必须取出不正确的日志。更正后的日志正确显示第 0 个元素的图片和音频值,但在尝试引用为 null 的标题数组的第 0 个元素时失败。这里的关键是音频值也是空的,但是引用这个值没有问题。这种行为似乎确实不一致。会尽快考虑尝试您的建议。 我已经展示了我在上面的主要问题中介绍的 try/catch 解决方法,效果很好。但是,我想了解这里出了什么问题,以便更好地了解 json。我敢说这可能是一个错误吗? 我打算回信讨论检查长度 - 长度和大小不同:***.com/questions/28920603/… 我自己已经开始做类似的事情来捕捉其他数组问题github.com/vahidhedayati/mailinglist/blob/master/src/groovy/…。你可以试试 github.com/vahidhedayati/mailinglist/blob/master/src/groovy/… 这样的东西,而不是 try catch 这显然是更多的经验 最后一次检查你说它们来自两个不同集合的两个空值你可以检查每一行中的空值实际类型是否相同,所以 println "$caption[currSlotNo].getClass() --" 并为具有空值的另一行执行此操作,并比较两个空类确保它们一开始就相同。正在考虑这是否证明是一种浪费,为什么不复制记录但第二行也是第三行 - 看看它是否比数据更像一个错误 【参考方案1】:

不确定 JSON 在此场景中涉及的位置,但查看上面的代码,您还有其他选择:

直到您将这些列表收集为标题 audioId picId

def picId = vidpNmList[0]
def audioId = vidpNmList[1]
def caption = vidpNmList[2]

你显示了一个关闭的输出:

def picId=[331, 332, 334, null, null, null, null, null, null, null, null, null]
    def audioId=[null, null, null, null, null, null, null, null, null, null, null, null]
    def Captions=[null, 333, 333, null, null, null, null, null, null, null, null]

现在这是我在玩列表:

    / you are current failing on this
    def pic=picId[0]


    //instead of above element[id] try .get(id)
    def cap=Captions.get(2)
    println "--- $pic @@@ $cap"

    //Then you can test by saying 
    if (cap&&something&&somethingEls)  
        doSomething
    

我回来了

--- 331  @@@ 333

无论如何,要在上面的列表中找到更多信息

编辑添加了关于 for 循环:

  for (def iC = 0; iC < jsonObject.caption.size() ; iC++)

在 groovy 中,for 循环通常应该这样表达:

int iC=0
for (iC < jsonObject.caption.size() ; iC++) 

总之试试这个:

jsonObject?.caption?.eachWithIndex item, i ->
   if (JSONObject.NULL.equals(item)  
      item=null
    

vidpNmList[2] = jsonObject.caption

如果失败,您可以尝试将其迭代到一个新列表,尽管我怀疑它是否真的需要:

def finalList=[]
jsonObject?.caption?.eachWithIndex item, i ->
   if (JSONObject.NULL.equals(item)  
      item=null
    
  finalList << item

vidpNmList[2] = finalList

比你的 for 循环版本更短更容易理解:) 我添加了 withIndex 和 i ,在你的情况下 if 是 item[i] 但没有必要,因为你已经在遍历每个元素,所以你甚至可以剪切它进一步向下:

jsonObject?.caption?.each item ->
   if (JSONObject.NULL.equals(item)  
      item=null
    

vidpNmList[2] = jsonObject.caption

您可能需要在上述所有示例中调整此if (JSONObject.NULL.equals(item) ,因为考虑到它,这不再是 json,所以是这样的:

if (!item ||(item && item=='null'))  
 item=null

【讨论】:

以上是关于Json 空数据行为异常的主要内容,如果未能解决你的问题,请参考以下文章

在 Python 3.3 中读取 JSON 文件的异常行为 [重复]

如何控制 json_encode 行为?

如何更改 Web Api Core 未经授权的行为

PostgreSQL 与 array_to_json 的奇怪行为

行为型模式---空对象模式

神秘的核心数据行为在第二次获取时检索空对象