使用 ColdFusion 附加到 JSON 数组,考虑 Null 值?

Append to JSON array with ColdFusion, taking Null values into consideration?

我已经在 Stack 上研究了一段时间,但我不相信我的大脑得到了如何做到这一点的提示。

我需要这个 JSON:

'{"loginHosts":["server1.example.com","server2.example.com"],"sudoHosts":["server1.example.com","server2.example.com"],"CPG":"my_group","mail":"test@example.com","loginShell":"/bin/bash"}'

看起来像这样JSON:

'{"loginHosts":["server1.example.com","server2.example.com","newserver1.example.com","newserver2.example.com"],"sudoHosts":["server1.example.com","server2.example.com","newserver1.example.com","newserver2.example.com"],"CPG":"my_group","mail":"test@example.com","loginShell":"/bin/bash"}'

有一些注意事项。

  1. 我从中提取的 JSON 应用程序要求返回这些字段,无论是否为空:loginHosts、sudoHosts、CPG、mail、loginShell。如果没有返回,应用程序会投诉。

  2. JSON 应用程序期望 loginHosts、sudoHosts 和 CPG 作为数组 [] 返回,即使为空。即:'{"loginHosts":[],"sudoHosts":[]}'

  3. 原始的 loginHosts 和 sudoHosts 数据(例如:server1.example.com、server2.example.com)必须保留在发送回应用程序的 JSON 字符串中。所以必须附加我所有的新数据。

  4. loginHosts 和 sudoHosts 有很多次作为 Null 数组发送到我的应用程序。即:'{"loginHosts":[],"sudoHosts":[]}'

我正在服务器 运行 Lucee 4.5 上开发这个 Linux OS。到get/set JSON 字符串;我使用 CFEXECUTE ssh 到远程 Linux 服务器到 pull/push 我的 JSON 字符串。你可以在这里看到原因:Populating SELECT with large JSON data set via ColdFusion (Lucee) very slow

我目前的代码:

    <cfset user_list = '{"loginHosts":["server1.example.com","server2.example.com"],"sudoHosts":["server1.example.com","server2.example.com"],"CPG":"my_group","mail":"test@example.com","loginShell":"/bin/bash"}'

<cfset arrayOfStructs = deserializeJson(user_list)>

<cfloop array="#arrayOfStructs#" index="user">
    <cfif structKeyExists(user, "loginHosts")>
        <cfloop array="#user.loginHosts#" index="login">
                <cfset loginHosts = #login#>
        </cfloop>
    </cfif>
    <cfif structKeyExists(user, "sudoHosts")>
        <cfloop array="#user.sudoHosts#" index="hosts">
            <cfset sudoHosts = #hosts#>
        </cfloop>
    </cfif>                             
    <cfif structKeyExists(user, "CPG")>
        <cfloop array="#user.CPG#" index="cp">
            <cfset CPG = #cp#>
        </cfloop>
    </cfif>
    <cfset mail = #user.mail#>
    <cfset loginShell = #user.loginShell#>
</cfloop>
<cfset my_servers = "newserver1.example.com,newserver2.example.com">
<cfset loginHosts = listAppend(loginHosts, "#my_servers#", ",")>
<cfset myStruct = '{"loginHosts":["#loginHosts#"],"sudoHosts":["#sudoHosts#"],"CPG":["#cp#"],"mail":"#mail#","loginShell":"#loginShell#"}'/>

然后使用我之前提到的 CFEXECUTE 方法将 myStruct 序列化并发送回远程服务器。

该代码有点用,但有两件事不起作用。首先,每个 cfset loginHosts 和 cfset sudoHosts 都只返回 JSON (server2.example.com) 中的第二个服务器。我知道我正在那个 CFLOOP 中覆盖我自己的 loginHosts 但我不确定如何更正它并检查 loginHosts 数组是否为 Null。

我在保留双引号以便它们保留在 JSON 中时也遇到了问题。在我的测试中我得到这个:

["server1.example.com","server2.example.com","newserver1.example.com,newserver2.example.com"]

注意到 newserver1 和 newserver2 之间缺少“,”了吗?

我试过将转义引号添加到我的 listAppend() 中,如下所示:“”“#my_servers”“”。它似乎工作正常,直到我在 JSON 字符串中返回一个 Null 值。

如有任何正确方向的推动,我们将不胜感激!

编辑 ---

一些说明:

原因:我只是想向数据库添加额外的服务器名称。要使用该数据库,我需要使用发送 JSON 并期望返回 JSON 的 API。这必须通过使用 curl 的 BASH shell 脚本来完成。正如我在上面发布的那样,这是原因:Populating SELECT with large JSON data set via ColdFusion (Lucee) very slow

我在我的应用程序中经常使用序列化JSON() 和反序列化JSON()。我代码顶部的 "user_list" 只是为了向您展示我要处理的数据。不是手写的

编辑 2 --

很抱歉没有将这一行添加到我上面的代码中。

底部的 'myStruct' 使用 "arrayOfStructs" 中的数据填充,然后序列化。

<cfset myJsonvar = serializeJSON(myStruct)/>

'myJsonvar' 然后使用 CFEXECUTE 通过 SSH 作为字符串发送到 BASH 脚本,然后使用 curl 提交数据。是的,令人费解,但由于安全原因,这是我所拥有的。

我会大大简化代码。看起来好像您所做的只是将您的两个新服务器添加到您的结构中现有的 loginHosts 列表中;不需要任何循环。

<cfset user_list = '{"loginHosts":["server1.example.com","server2.example.com"],"sudoHosts":["server1.example.com","server2.example.com"],"CPG":"my_group","mail":"test@example.com","loginShell":"/bin/bash"}'>

<cfset myStruct = deserializeJson(user_list)>

<cfset myServers = ["newserver1.example.com","newserver2.example.com"]>

<!--- if loginHosts isn't an array, make it one. --->
<cfif NOT structKeyExists(myStruct, 'loginHosts') OR NOT isArray(myStruct.loginHosts)> 
  <cfset myStruct.loginHosts = []>
</cfif>
<cfset arrayAppend(myStruct.loginHosts, myServers, true)>

<cfset user_list = serializeJSON(myStruct)>
<!--- now user_list is a json string with your new servers added as login hosts, the rest of the struct remains the same. --->