Arrays 使用ColdFusion附加到JSON数组,并考虑空值?

Arrays 使用ColdFusion附加到JSON数组,并考虑空值?,arrays,json,coldfusion,lucee,Arrays,Json,Coldfusion,Lucee,我已经在堆栈上挖掘了一段时间,但我不相信我的大脑得到了如何做的提示 我需要这个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"],"sudoHosts":["server1.example.com","server2.example.com"],"CPG":"my_group","mail":"test@example.com","loginShell":"/bin/bash"}'
要看起来像这样,请执行以下操作:

'{"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"}'
这里有一些警告

  • 我从中提取的JSON应用程序要求返回以下字段,无论是否为null:loginHosts、sudoHosts、CPG、mail、loginShell。如果未返回,则应用程序会投诉

  • JSON应用程序期望loginHosts、sudoHosts和CPG以数组[]的形式返回,即使为null也是如此。即:“{“登录主机”:[],“sudoHosts”:[]}”

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

  • 很多时候,loginHosts和sudoHosts会作为空数组发送到我的应用程序。即:“{“登录主机”:[],“sudoHosts”:[]}”

  • 我正在运行Lucee4.5和Linux操作系统的服务器上开发这个。获取/设置JSON字符串;我使用CFEXECUTE通过ssh连接到远程Linux服务器来拉/推我的JSON字符串。你可以在这里看到原因:

    到目前为止,我掌握的代码是:

        <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#"}'/>
    
    注意到newserver1和newserver2之间缺少“?”

    我尝试过向listAppend()添加转义引号,如下所示:“#我的_服务器”。在JSON字符串中返回空值之前,它似乎工作正常

    任何朝正确方向的轻推都将不胜感激

    编辑---

    一些澄清:

    原因:我只是想向数据库添加额外的服务器名称。要使用该数据库,我需要使用一个发送JSON并期望返回JSON的API。这必须通过利用curl的bashshell脚本来完成。如上所述,这就是原因:

    我在应用程序中经常使用serializeJSON()和deserializeJSON()。我代码顶部的“用户列表”只是为了向您展示我要处理的数据。这不是手写的

    编辑2--

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

    底部的“myStruct”由“arrayOfStructs”中的数据填充,然后序列化

    <cfset myJsonvar = serializeJSON(myStruct)/>
    
    
    

    然后使用CFEXECUTE通过SSH将“myJsonvar”作为字符串发送到BASH脚本,然后使用curl提交数据。是的,很复杂,但由于安全性的原因,这就是我所拥有的。

    我会将代码简化很多。看起来,您所做的只是将两个新服务器添加到结构中现有的登录主机列表中;这不需要任何循环

    <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. --->
    
    
    
    您的最后一行是个问题(但不确定它是否是“问题”)。它应该只是创建一个结构,而不是json字符串。我不明白为什么您不从一开始就修改原始结构(作为结构),或者当您可以直接访问一个键,然后在嵌套数组上循环时,为什么要循环它。您所做的只是将两个新服务器添加到登录主机阵列中,对吗?例如,
    会将两个新服务器添加到原始结构的
    登录主机阵列中。根据需要,服务器的数量可以从1到N条记录不等。我之所以循环使用它,是因为JSON字段loginHosts、sudoHosts和CPG是数组。我的理解是,为了附加到现有数据,您必须先设置数据,然后再附加?我想我完全错了(因为arrayAppend可以合并两个阵列,所以只要阵列中有服务器,您要添加的服务器数量就无关紧要。Kevin,我正在尝试Leigh的建议,以及这一建议。这将让你们知道什么是有效的。我非常确定,当涉及空值时,它们都会有相同的问题。isArray可能是最佳的选择。)测试loginHosts是否包含一个数组,而不是测试它是否为空。添加了一个检查,可以纠正存在和不存在数组的两种情况,如果它根本不存在只是为了安全。Kevin B-Darn。让我来试试:)(编辑)听起来数组不是空的,在这种情况下,上述方法就可以了@Grimdari-两个答案都是一样的,但是Kevin的更好,所以我删除了我的。合并数组希望它存在这么久,现在它真的存在了。。。我总是忘记;-)
    
    <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. --->