在 ColdFusion 中 JSON 数组中追加一个 JSON 数组。

3
这里是一道后续问题:在ColdFusion中追加JSON数组时如何处理null值的基础上。
那个问题昨天已经有答案,而且非常完美(感谢 Kevin B. 和 Leigh!)。然而,今天早上我的应用程序却对我提出了一个难题。根据请求的数据不同,有时返回整个JSON作为如下的数组:Sometimes
[
   {
      "loginHosts": [
         "server1.example.com"
      ],
      "sudoHosts": [
         "server1.example.com"
      ],
      "CPG": [
         "my_group"
      ],
      "mail": "myuser@example.com",
      "loginShell": "/bin/bash"
   }
]

我不知道为什么该应用会这样。如果我知道这是可能发生的事情,我会在之前的问题中添加这些信息,抱歉。
我的尝试寻找解决方案首先让我来到这里:使用Coldfusion处理JSON数据。作为一个集合遍历JSON数组似乎是可以工作的,但仅当数组值均非空时才有效。我认为如果我将该代码用于所有JSON字段,则与之前的问题一样,它也会起作用:
<cfif NOT structKeyExists(myStruct, 'sudoHosts') OR NOT isArray(myStruct.sudoHosts)> 
  <cfset myStruct.sudoHosts = []>
</cfif>

这并不是这种情况。我一直收到以下错误信息:

Error: Can't cast Complex Object Type Array to String

通过查看调试输出,Lucee 排除了这个问题:string Use Built-In-Function "serialize(Array):String" to create a String from Array。我更深入地挖掘了一下,并发现了这篇文章:Railo tip: store complex data by using serialize(data)。遗憾的是,空值又来找麻烦了。另外,我的理解是serialize()类似于evaluate(),而且不建议使用。
我将继续寻找解决方案,但任何帮助都将不胜感激!
-- 编辑 --
我看到了这个帖子:ColdFusion JSON object vs array of objects。我注意到问题中的 JSON 是一个数组[],并将答案应用到了我的代码中,但仍然遇到了空值问题。我想我不知道如何检查嵌套的空值。 :(

你为什么认为这样说:“另外,我理解serialize()类似于evaluate(),不适合使用。”? - Dan Bracuk
Evaluate()往往会慢一些,即使它的速度略慢,而serialize()似乎与evaluate()类似。我找到的最好的例子在这里:http://blog.adamcameron.me/2013/08/evalulate-is-really-slow-is-it-now.html。在阅读了其他各种文档之后,serialize()似乎具有相同的开销。每个人的情况可能都不同。 :D - Grimdari
1个回答

1

一步一步来。

理想情况下,你应该确定为什么响应不同。由于你说这些差异通常对应于你的请求中的某些不同之处,这强烈表明你可能忽略了(或可能误解了)远程API中的某些内容。我建议重新审查API以识别那个“东西”,以便找出正确的方法。否则,随着你继续调整代码以处理每种“新”情况,代码将很快变得难以管理和低效。

如果由于某种原因API确实无故返回不同的结果,则你最好根据自己的期望编写代码,并在收到其他内容时优雅地失败。首先列出预期的可能性:

  1. 响应是包含特定键的单个结构体 或
  2. 响应是包含特定键的结构体数组
基于以上内容,您可以使用IsArrayIsStruct函数来确定响应的格式,并相应地处理它。首先检查反序列化对象。如果它是一个数组,则提取第一个元素中的结构(请注意,我假设数组只包含单个元素,如示例所示。如果它可以包含多个元素,则需要进行额外处理)。
<cfset data = deserializeJson(originalJSON)>
....
<!--- Extract structure from first element of array --->
<cfif IsArray(data) && arrayLen(data)>
    <cfset data = data[1]>
</cfif>

接下来,请确认您正在处理一个包含所需键的结构。如果是这样,请继续进行常规处理。否则,发生了意外情况,代码应执行适当的错误处理。

<!--- Verify object is a structure and contains expected key(s) --->
<cfif IsStruct(data) && structKeyExists(data, "loginHosts")>
    ... process data as usual
<cfelse>
    ... data is not in expected format, do  error handling here
</cfif>

上面是一个非常简单粗暴的例子,但应该演示了基本思想。只要您确定正在正确使用API,您所能做的就是编写预期的代码,并在发生不同情况时优雅地失败。

我正在处理这个问题,需要一些时间完成。 - Grimdari
虽然“处理预期条件,并对其他情况进行优雅失败”的基本前提是正确的,但您应该真正努力找出它发生的原因。原因在于,如果您误解了API,并且数组可能包含多个元素,则需要采取不同的方法。 - Leigh
我打了几个电话。显然API还没有完全实现。我发现的只是已经实现的功能的一部分。现在我只能继续处理它。另外,你上面的建议很有效。cfset data = data [1] 在我的脑海中点亮了一个灯泡:D。但是,它引起了另一个问题,我正在努力解决。 - Grimdari
再次感谢你,Leigh。我的下一个挑战是将这个:'{"sudoHosts":"newserver1.example.com"}' 转换成这个:'{\"sudoHosts\":\"newserver1.example.com\"}',以便可以通过SSH正确地发送到另一台服务器上的BASH脚本。有趣的日子!:D - Grimdari
可能实际上是一个合法的双重序列化用例;-) serializeJSON(serializeJSON(obj)) - Leigh
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接