使用嵌套的结构数组创建Coldfusion JSON结构

时间:2016-08-18 21:02:45

标签: arrays json rest coldfusion

在ColdFusion中(REST / C,我试图填充一个名为&#34的结构;存储"。嵌套在里面是一个Reports数组,嵌套在Reports中的是一个Pics数组。同样嵌套在Reports中的是一系列问题,嵌套在问题中的是一组答案。

注意:每个商店可以有多个报告,每个报告可以包含多个图片和几个问题,每个问题可以有多个答案。

最终的JSON应如下所示......

stores:[
{"storeid":"101","storename":"STORE101",reports:[
    {"reportid":"201","reportname":"REPORT201","pics":[
        {"picid":"301","pictitle":"SOMEPIC1"},{"picid":"302","pictitle":"SOMEPIC2"}
    ],"questions":[
        {"questionid":"111","question":"What is your favorite color?","answers":[
            {"answerid":"555","answer":"Blue"},{"answerid":"556","answer":"Green"},{"answerid":"557","answer":"Red"}
        ]},{"questionid":"222","question":"What is your favorite car?","answers":[
            {"answerid":"655","answer":"Ferrari"},{"answerid":"656","answer":"Mustang"},{"answerid":"657","answer":"Porsche"}
        ]}
    ]},{"reportid":"202","reportname":"REPORT202","pics":[
        {"picid":"304","pictitle":"SOMEPIC4"},{"picid":"305","pictitle":"SOMEPIC5"}
    ],"questions":[
        {"questionid":"111","question":"What is your favorite color?","answers":[
            {"answerid":"555","answer":"Blue"},{"answerid":"556","answer":"Green"},{"answerid":"557","answer":"Red"}
        ]},{"questionid":"222","question":"What is your favorite car?","answers":[
            {"answerid":"655","answer":"Ferrari"},{"answerid":"656","answer":"Mustang"},{"answerid":"657","answer":"Porsche"}
        ]}
    ]},
    ]},{"reportid":"203","reportname":"REPORT103","pics":[
        {"picid":"307","pictitle":"SOMEPIC7"},{"picid":"308","pictitle":"SOMEPIC8"}
    ],"questions":[
        {"questionid":"111","question":"What is your favorite color?","answers":[
            {"answerid":"555","answer":"Blue"},{"answerid":"556","answer":"Green"},{"answerid":"557","answer":"Red"}
        ]},{"questionid":"222","question":"What is your favorite car?","answers":[
            {"answerid":"655","answer":"Ferrari"},{"answerid":"656","answer":"Mustang"},{"answerid":"657","answer":"Porsche"}
        ]}
    ]},
{"storeid":"102","storename":"STORE102",reports:[
    {"reportid":"201","reportname":"REPORT201","pics":[
        {"picid":"301","pictitle":"SOMEPIC1"},{"picid":"302","pictitle":"SOMEPIC2"}
    ],"questions":[
    ],"questions":[
        {"questionid":"111","question":"What is your favorite color?","answers":[
            {"answerid":"555","answer":"Blue"},{"answerid":"556","answer":"Green"},{"answerid":"557","answer":"Red"}
        ]},{"questionid":"222","question":"What is your favorite car?","answers":[
            {"answerid":"655","answer":"Ferrari"},{"answerid":"656","answer":"Mustang"},{"answerid":"657","answer":"Porsche"}
        ]}
    ]},{"reportid":"202","reportname":"REPORT202","pics":[
        {"picid":"304","pictitle":"SOMEPIC4"},{"picid":"305","pictitle":"SOMEPIC5"}
    ],"questions":[
        {"questionid":"111","question":"What is your favorite color?","answers":[
            {"answerid":"555","answer":"Blue"},{"answerid":"556","answer":"Green"},{"answerid":"557","answer":"Red"}
        ]},{"questionid":"222","question":"What is your favorite car?","answers":[
            {"answerid":"655","answer":"Ferrari"},{"answerid":"656","answer":"Mustang"},{"answerid":"657","answer":"Porsche"}
        ]}
    ]},
    ,{"reportid":"203","reportname":"REPORT103","pics":[
        {"picid":"307","pictitle":"SOMEPIC7"},{"picid":"308","pictitle":"SOMEPIC8"}
    ],"questions":[
        {"questionid":"111","question":"What is your favorite color?","answers":[
            {"answerid":"555","answer":"Blue"},{"answerid":"556","answer":"Green"},{"answerid":"557","answer":"Red"}
        ]},{"questionid":"222","question":"What is your favorite car?","answers":[
            {"answerid":"655","answer":"Ferrari"},{"answerid":"656","answer":"Mustang"},{"answerid":"657","answer":"Porsche"}
        ]}
    ]},
    ]},
{"storeid":"103","storename":"STORE103",reports:[
    {"reportid":"201","reportname":"REPORT201","pics":[
        {"picid":"301","pictitle":"SOMEPIC1"},{"picid":"302","pictitle":"SOMEPIC2"}
    ],"questions":[
        {"questionid":"111","question":"What is your favorite color?","answers":[
            {"answerid":"555","answer":"Blue"},{"answerid":"556","answer":"Green"},{"answerid":"557","answer":"Red"}
        ]},{"questionid":"222","question":"What is your favorite car?","answers":[
            {"answerid":"655","answer":"Ferrari"},{"answerid":"656","answer":"Mustang"},{"answerid":"657","answer":"Porsche"}
        ]}
    ]},
    {"reportid":"202","reportname":"REPORT202","pics":[
        {"picid":"304","pictitle":"SOMEPIC4"},{"picid":"305","pictitle":"SOMEPIC5"}
    ],"questions":[
        {"questionid":"111","question":"What is your favorite color?","answers":[
            {"answerid":"555","answer":"Blue"},{"answerid":"556","answer":"Green"},{"answerid":"557","answer":"Red"}
        ]},{"questionid":"222","question":"What is your favorite car?","answers":[
            {"answerid":"655","answer":"Ferrari"},{"answerid":"656","answer":"Mustang"},{"answerid":"657","answer":"Porsche"}
        ]}
    ]},
    {"reportid":"203","reportname":"REPORT103","pics":[
        {"picid":"307","pictitle":"SOMEPIC7"},{"picid":"308","pictitle":"SOMEPIC8"}
    ],"questions":[
        {"questionid":"111","question":"What is your favorite color?","answers":[
            {"answerid":"555","answer":"Blue"},{"answerid":"556","answer":"Green"},{"answerid":"557","answer":"Red"}
        ]},{"questionid":"222","question":"What is your favorite car?","answers":[
            {"answerid":"655","answer":"Ferrari"},{"answerid":"656","answer":"Mustang"},{"answerid":"657","answer":"Porsche"}
        ]}
    ]},
    ]}
]

以下是我失败的代码。

    <!--- MY REPORTS (GET) --->
    <cffunction name="getmyreports" access="remote" returntype="any" produces="application/json" httpmethod="get" restpath="/myreports/{user_id}/{device_id}/{token}">
        <cfargument name="user_id" required="true" type="numeric" restargsource="path"/>
        <cfargument name="device_id" required="true" type="string" restargsource="path"/>
        <cfargument name="token" required="true" type="string" restargsource="path"/>


<cfquery name="r" datasource="#this.dsn#">
    SELECT          rt.report_type_id, rt.report_type, rd.user_id, u.firstname, u.lastname, u.username, rn.priority, rn.start_date, rn.aid, 
                            rn.report_id, rn.report_name, rn.exp_date, rn.report_num, 
                            rn.pic_num, rn.report_type, rn.report_date, rn.est_hrs, 
                            rd.report_id, rd.report_complete, rd.report_status, rd.complete_date, 
                            rd.report_data_id, rd.comments, rd.resubmit, s.storeid, s.client_loc, s.city, s.state
    FROM                report_types rt, users u, report_name rn, report_data rd, stores s
    WHERE           u.user_id=rd.user_id
    AND                 rd.storeid=s.storeid 
    AND                     rt.report_type_id=rn.report_type  
    AND                 rn.report_id=rd.report_id 
    AND                     rn.report_name_status = 1
    <cfif auth.usertype eq 4>AND rn.report_type = 172</cfif><!--- audit only --->
    AND                     rd.report_status = 0 <!--- not completed ---> <!---not in (7) get rid of unassigned reports--->
    AND                 u.user_id=#Val(auth.user_id)# 
    AND                     rn.exp_date >= #Now()# 
    ORDER BY s.client_loc, rn.exp_date DESC, rn.report_name
</cfquery>

<cfset stores={}>

<cfif r.recordcount>

<cfset snum=1>

<cfoutput query="r" group="client_loc">

    <!--- STORES --->
    <cfset stores['stores']['store[#snum#]']['storeid'] = "#storeid#">
    <cfset stores['stores']['store[#snum#]']['store'] = "#client_loc# - #city#, #state#">

    <cfset rnum=1>
    <cfoutput>

        <!--- REPORTS --->
        <cfset stores['stores']['store[#snum#]']['reports']['report[#rnum#]']['report_id'] = "#report_id#">
        <cfset stores['stores']['store[#snum#]']['reports']['report[#rnum#]']['report_data_id'] = "#report_data_id#">

            <!--- PICS --->
            <cfquery name="p" datasource="#this.dsn#">
                SELECT report_id,pic_title_id,pic_title,pic_order
                FROM pic_titles
                WHERE report_id = #report_id#
                ORDER BY pic_order
             </cfquery>

            <cfset pnum=1>
            <cfloop query="p">
                <cfset stores['stores']['store[#snum#]']['reports']['report[#rnum#]']['report_data']['pics']['pic[#pnum#]']['pic_title_id'] = "#p.pic_title_id#">
                <cfset stores['stores']['store[#snum#]']['reports']['report[#rnum#]']['report_data']['pics']['pic[#pnum#]']['pic_title'] = "#p.pic_title#">
                <cfset stores['stores']['store[#snum#]']['reports']['report[#rnum#]']['report_data']['pics']['pic[#pnum#]']['pic_order'] = "#p.pic_order#">
                <cfset pnum=pnum+1>
            </cfloop>

            <!--- QUESTIONS --->
            <cfquery name="q" datasource="#this.dsn#">
                SELECT r.report_id,r.question_id,r.question_order,v.question,v.question_stock,v.allow_comment
                FROM vendor_questions v, report_questions_chosen r
                WHERE v.question_id=r.question_id
                AND r.report_id = #report_id#
                ORDER BY r.report_id, r.question_order
             </cfquery>

            <cfset qnum=1>
            <cfloop query="q">
                <cfset stores['stores']['store[#snum#]']['reports']['report[#rnum#]']['report_data']['questions']['q[#qnum#]']['question_id'] = "#q.question_id#">
                <cfset stores['stores']['store[#snum#]']['reports']['report[#rnum#]']['report_data']['questions']['q[#qnum#]']['question'] = "#q.question#">
                <cfset stores['stores']['store[#snum#]']['reports']['report[#rnum#]']['report_data']['questions']['q[#qnum#]']['question_order'] = "#q.question_order#">
                <cfset stores['stores']['store[#snum#]']['reports']['report[#rnum#]']['report_data']['questions']['q[#qnum#]']['question_stock'] = "#q.question_stock#">
                <cfset stores['stores']['store[#snum#]']['reports']['report[#rnum#]']['report_data']['questions']['q[#qnum#]']['allow_comment'] = "#q.allow_comment#">

                <cfif q.question_stock eq "Y">
                    <!--- ANSWERS --->
                    <cfquery name="a" datasource="#this.dsn#">
                        SELECT a.question_id, a.answer_id, a.answer
                        FROM vendor_questions v, report_questions_chosen r, vendor_answers a 
                        WHERE v.question_id=r.question_id
                        AND a.question_id = v.question_id 
                        AND r.report_id = #r.report_id# 
                        AND v.question_id = #q.question_id#
                        AND is_active = 1
                        ORDER BY question_id, answer_status
                    </cfquery>

                    <cfset anum=1>
                    <cfloop query="a">
                        <cfset stores['stores']['store[#snum#]']['reports']['report[#rnum#]']['report_data']['questions']['q[#qnum#]']['answers']['a[#anum#]']['question_id'] = "#a.question_id#">
                        <cfset stores['stores']['store[#snum#]']['reports']['report[#rnum#]']['report_data']['questions']['q[#qnum#]']['answers']['a[#anum#]']['answer_id'] = "#a.answer_id#">
                        <cfset stores['stores']['store[#snum#]']['reports']['report[#rnum#]']['report_data']['questions']['q[#qnum#]']['answers']['a[#anum#]']['answer'] = "#a.answer#">
                        <cfset anum=anum+1>
                    </cfloop>                

                </cfif>

                <cfset qnum=qnum+1>
            </cfloop>


            <cfset rnum=rnum+1>

    </cfoutput>

    <cfset snum=snum+1>
</cfoutput>

<cfelse>

      <cfset stores['stores']['error'] = "No reports">

</cfif>


<cfset mystores = serializeJSON(stores) />

        <cfreturn mystores> 
    </cffunction>    

CFDUMP看起来并不好,但生成的JSON是不可接受的。

CFDUMP

JSON失败(部分代码段)。正确的JSON将包含结构数组。如何在CF或CFSCRIPT中创建适当的结构数组

例如,我不应该看到&#34;存储[3]&#34;和&#34;报告[2]&#34;在JSON中,它应该只是一个名称为:值对的结构数组。

{"stores":{"store[3]":{"reports":{"report[3]":{"report_data":{"questions":{"q[1]":{"question_stock":"N","question":"Did you complete the training...

结论 为了增加混淆,有几个查询,有几个循环来获取填充数组所需的所有数据。我无法绕过它。感谢您提供的任何帮助,指出我正确的方向。

2 个答案:

答案 0 :(得分:2)

  

如何循环查询结果并填充   数组而不必使用store[1]store[2]

根据评论,关于该功能的其他一些提示:

  1. 我认为你正在接近它:)没有必要跟踪数组位置。每次循环,创建一个新的&#34;商店&#34;结构(&#34;报告&#34;等等)。然后根据需要填充对象。完成后,将当前对象追加到正确的数组或结构中并将其忘记。由于您一次只使用一个&#34; store&#34;,&#34; report&#34;等等(即当前的一个),因此无需担心位置或索引。

    <cfset storeArray = []>
    <cfloop ...>
    
        <!--- create a new store object --->
        <cfset currStore = { "reports" = [] }>
         ... populate ....
    
        <cfloop ....>
            <!--- create a new report object --->
            <cfset currReport = { "pics" = [], "questions" = [] }>
            ... populate ....
    
           <!--- add to array --->
           <cfset arrayAppend( currStore.reports, currReport )>
    
        </cfloop>
    
        <!--- add to array --->
        <cfset arrayAppend( storeArray, currStore )>
    
    </cfloop>
    
  2. 与问题没有直接关系,但始终使用cfqueryparam。除了提供sql注入保护之外,它还有助于在多次执行相同语句时提高查询性能,如此处所示。

  3. 不要忘记本地化所有函数局部变量。这包括查询名称,循环索引变量 - 仅在函数内部使用的任何变量。使用VARLOCAL确定这些变量的范围可确保它们不会泄漏到共享variables范围内,这可能会导致奇怪且难以在特定条件下重现错误(只需在{ {3}})。

答案 1 :(得分:1)

LocationManager lm; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); LocationManager lm = (LocationManager)getSystemService(Context.LOCATION_SERVICE); lm.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, new LocationListener() { @Override public void onStatusChanged(String provider, int status, Bundle extras) {} @Override public void onProviderEnabled(String provider) {} @Override public void onProviderDisabled(String provider) {} @Override public void onLocationChanged(Location location) {} }); setMockLocation(15.387653, 73.872585, 500); } private void setMockLocation(double latitude, double longitude, float accuracy) { lm.addTestProvider (LocationManager.GPS_PROVIDER, "requiresNetwork" == "", "requiresSatellite" == "", "requiresCell" == "", "hasMonetaryCost" == "", "supportsAltitude" == "", "supportsSpeed" == "", "supportsBearing" == "", android.location.Criteria.POWER_LOW, android.location.Criteria.ACCURACY_FINE); Location newLocation = new Location(LocationManager.GPS_PROVIDER); newLocation.setLatitude(latitude); newLocation.setLongitude(longitude); newLocation.setAccuracy(accuracy); lm.setTestProviderEnabled(LocationManager.GPS_PROVIDER, true); lm.setTestProviderStatus(LocationManager.GPS_PROVIDER, LocationProvider.AVAILABLE, null,System.currentTimeMillis()); lm.setTestProviderLocation(LocationManager.GPS_PROVIDER, newLocation); } 但那是你的代码! 从简单开始,尝试了解它的工作原理:

I shouldn't have to see "store[3]" and "report[2]" in the JSON