eduski
eduski

Reputation: 179

Convert coldfusion json to struct

I have a JSON variable output from a jQuery application as so:

[{"id":1},
{"id":197,"children":[{"id":198},{"id":199},{"id":200}]},
{"id":2,"children":[{"id":3},{"id":4},{"id":143},{"id":6},{"id":5},{"id":7},{"id":8},{"id":9},{"id":10},{"id":11},{"id":12}]},
{"id":15,"children":[{"id":17},{"id":190},{"id":191},{"id":131},{"id":16},{"id":142},{"id":124}]},
{"id":149,"children":[{"id":150},{"id":160},{"id":161},{"id":184}]},
{"id":20,"children":[{"id":132},{"id":127},{"id":152},{"id":107},{"id":108},{"id":109},{"id":110},{"id":125},{"id":128},{"id":130},{"id":129},{"id":112}]},
{"id":162,"children":[{"id":163},{"id":164},{"id":165},{"id":166},{"id":186},{"id":187}]},
{"id":167,"children":[{"id":173},{"id":168},{"id":170},{"id":169},{"id":192},{"id":194}]},
{"id":174,"children":[{"id":176},{"id":175},{"id":188}]},
{"id":153,"children":[{"id":178},{"id":179},{"id":195},{"id":154},{"id":157}]},
{"id":180,"children":[{"id":181},{"id":182},{"id":183},{"id":189}]},
{"id":122},
{"id":21},
{"id":13},
{"id":92},
{"id":22},
{"id":113},
{"id":114}]

I need to convert this variable to a struct and then loop the struct by the first id parameter to find the children for each id (if there is one). I have tried to convert it as a structure like so but I am getting an error:

<cfset jsonarray = deserializeJson(output)>
<cfloop collection="#jsonarray#" index="id">
<cfdump var="#jsonarray[id]#">
</cfloop>

It does not recognize the variable as a structure:

Invalid collection [{id={1}}, {children={[{id={198}}, {id={199}}, {id={200}}]},id={197}}, {children={[{id={3}}, {id={143}}, {id={4}}, {id={6}}, {id={5}}, {id={7}}, {id={8}}, {id={9}}, {id={10}}, {id={11}}, {id={12}}]},id={2}}, {children={[{id={17}}, {id={190}}, {id={191}}, {id={131}}, {id={16}}, {id={142}}, {id={124}}]},id={15}}, {children={[{id={150}}, {id={160}}, {id={161}}, {id={184}}]},id={149}}, {children={[{id={132}}, {id={127}}, {id={152}}, {id={107}}, {id={108}}, {id={109}}, {id={110}}, {id={125}}, {id={128}}, {id={130}}, {id={129}}, {id={112}}]},id={20}}, {children={[{id={163}}, {id={164}}, {id={165}}, {id={166}}, {id={186}}, {id={187}}]},id={162}}, {children={[{id={173}}, {id={168}}, {id={170}}, {id={169}}, {id={192}}, {id={194}}]},id={167}}, {children={[{id={176}}, {id={175}}, {id={188}}]},id={174}}, {children={[{id={178}}, {id={179}}, {id={195}}, {id={154}}, {id={157}}]},id={153}}, {children={[{id={181}}, {id={182}}, {id={183}}, {id={189}}]},id={180}}, {id={122}}, {id={21}}, {id={13}}, {id={92}}, {id={22}}, {id={113.... Must be a valid structure or COM object. 

Upvotes: 9

Views: 14565

Answers (3)

Fergus
Fergus

Reputation: 2982

I created an Angular 1.4 ColdFusion 9 JSON Normalizer here

 var myURL = 'myCfc.cfc?method=getItemsFromDb';
 var app = angular.module('angularOutput',[]);
 app.controller("sectionController", function($scope, $http) {
      $http.get(myURL).
        success(function(data, status, headers, config) {
          var log = []; 
          var output = '';
          angular.forEach(data.DATA, function(value, key) {
                    this.push(output +='{"value": ');
                    this.push(output += '"'+value[0]+'"');
                    this.push(output +=',"text":');
                    this.push(output += '"'+value[1]+'"');
                    this.push(output +='}');
                    this.push(output +=',');
                }, log);
              output = output.replace(/,\s*$/, "");/*had to remove the final comma */
              output = '['+output+']'; /*had to add the [] to corectally form the output*/

          $scope.sections = angular.fromJson(output);
        }).
        error(function(data, status, headers, config) {
          console.log(data);
        });
    });

Upvotes: 1

Kevin Mansel
Kevin Mansel

Reputation: 2371

A tidy cfscript version. :)

<cfscript>
    structObj = deserializeJson(jsonString);

    for(i = 1; i LTE ArrayLen(structObj); i++){

        WriteOutput("parent id : " & structObj[i].id & "<br>"); 
        if(StructKeyExists(structObj[i], "children")){
            for(j = 1; j LTE ArrayLen(structObj[i].children); j++){
                WriteOutput("    -children id : " & structObj[i].children[j].id & "<br>");
            }
        }
    }
</cfscript>

Upvotes: 2

Leigh
Leigh

Reputation: 28873

In JSON, the [] denotes an array and {} a structure (or object). So your input is actually an array of structures. You need to use an array loop, not a collection loop:

<cfset arrayOfStructs = deserializeJson(output)>
<cfloop array="#arrayOfStructs#" index="parent">
      <cfset parentID = parent.id />
      ... 
</cfloop>

children is also an array of structures. Inside the outer loop, check for the existence of that key. If found, loop through the child array and do something with each of the id's:

  <cfif structKeyExists(parent, "children")>
      <cfloop array="#parent.children#" index="child">
          ...
      </cfloop>
  </cfif>

Upvotes: 15

Related Questions