designetwork(EN)

IT technical memo of networking

Get data with hierarchical JSON objects by Node.js

f:id:daichi703n:20161118195543j:plain

Node.js (JavaScript) is often used to handle JSON data, such as obtaining information from the API. JSON is a structured data format, and it can also be a hierarchical structure (nested structure).

I will introduce the procedure for acquiring specific data (element) of a child object with nested JSON. In short, take the length of the child object, loop it with for and pick it up with if.

Assumption required modules

npm install sync-request Perform synchronization processing.

npm install util Dump JSON objects.

Test with Redmine API

As a sample, use the API of Redmine I'm using.

For information on Redmine's API see the official site.

Rest api - Redmine

Node.js source code

The source code for obtaining JSON from the Redmine API and acquiring a specific object from the hierarchy are as follows. I will explain each part below.

Obtain the number of tickets for all the statuses (including closed)

If you get it like this, you get only the open ticket if it is normal. You will see that total_count is less than the latest ticket number.

http://<Redmine URL>/issues.json?key=<API Access Key>

At this time, it is necessary to specify the statusID=*(%2a) when all the tickets are GET.

http://<Redmine URL>/issues.json?status_id=%2a&key=<API Access Key>

Get tickets with JSON

The function to get the ticket is redmineGet. I use ticketLimit to get only the test ticket. (Pass from main)

function redmineGet(ticketLimit){
  var ticketJson, ticketOffset=0;
  var ticketUrl="<Redmine URL>", ticketKey="<API Access Key>";
  var response = request(
    'GET',
    'http://'+ticketUrl+'/issues.json?status_id=*&limit='+ticketLimit+'&offset='+ticketOffset+'&key='+ticketKey
    );
    if (response.statusCode == 200) {
      //console.log("Redmine : "+response.body);
      ticketJson = JSON.parse(response.body);
      return ticketJson;
    }
}

When parsing JSON it has such a structure. The part which is [Object] is Object as described, the hierarchy is deep, it is necessary to dump it one more step. (Omitted here)

Also, in this method, tickets are acquired in descending order.

{ issues: 
   [ { id: 101,
       project: [Object],
       tracker: [Object],
       status: [Object],
       priority: [Object],
       author: [Object],
       assigned_to: [Object],
       category: [Object],
       subject: 'Post entry about Node.js',
       description: '',
       start_date: '2016-11-18',
       done_ratio: 0,
       custom_fields: [Object],
       created_on: '2016-11-18T01:15:59Z',
       updated_on: '2016-11-18T08:56:39Z' },
     { id: 100,
       project: [Object],
       <snip>
       created_on: '2016-11-18T01:10:02Z',
       updated_on: '2016-11-18T06:36:54Z' } ],
  total_count: 101,
  offset: 0,
  limit: 4 }

Get hierarchical JSON objects

Information on each acquired object (= ticket) is acquired. This time we will target Redmine's custom field.

Custom fields can be created arbitrarily by the user, and can be added according to the application. For this examination, we have made items "defect number", "request source" and "system".

The hierarchical structure of JSON is as follows.

{ issues: 
   [ { id: 99,
       subject: 'Node.js does not work',
       <snip>
       custom_fields: { id: 1, name: 'defect number', value: '634' },
                      { id: 3, name: 'request source', value: 'Sales' },
                      { id: 4, name: 'system', value: 'GitHub' },

This time we will extract tickets whose "system" is "HatenaBlog".

Each item is managed by id in the custom field. As a general usage, these are switched on/off by tracker. Therefore, the number of items (index number) will change according to the ticket as follows.

Among them, "HatenaBlog ticket !!" is attached to the extraction object. (Source code is described later)

101
'Post entry about Node.js'

 customFields : 
  index: 0 | id: 4  name: system  value: HatenaBlog
  HatenaBlog ticket!!

100
'Node.js cannot GET JSON'

 customFields : 
  index: 0 | id: 1  name: defect number  value: 635
  index: 1 | id: 3  name: request source  value: Support
  index: 2 | id: 4  name: system  value: HatenaBlog
  HatenaBlog ticket!!

99
'Node.js does not work'

 customFields : 
  index: 0 | id: 1  name: defect number  value: 634
  index: 1 | id: 3  name: request source  value: Sales
  index: 2 | id: 4  name: system  value: GitHub

98
'Get data with hierarchical JSON objects by Node.js'

 customFields : 
  index: 0 | id: 3  name: request source  value: Sales
  index: 1 | id: 4  name: system  value: Redmine

In nested JSONs, consideration is required to follow changing index numbers.

Get the number of elements of the object with a simple way of thinking, and for loop for the number of elements. By judging if at each index, the target is extracted.

var customFieldsLength, cf=["id", "name", "value"]; //cf:Custom Fields
for(var i=0; i<ticketCount; i++){
  console.log("\n");dump(returnJson["issues"][i]["id"]);dump(returnJson["issues"][i]["subject"]);

  customFieldsLength = returnJson["issues"][i]["custom_fields"].length;
  console.log("\n customFields : ");
  for(var j=0; j<customFieldsLength; j++){
    cf = returnJson["issues"][i]["custom_fields"][j];
    console.log("  index: "+j+" | id: "+cf.id+"  name: "+cf.name+"  value: "+cf.value);
    if((cf.id==4) && (cf.value == "HatenaBlog")){console.log("  HatenaBlog ticket!!");}
  }
}

Conclusion

We get hierarchical JSON with Node.js (javascript) and extracted specific data of child objects.

It can be applied when organizing information such as Redmine's ticket list.


This Blog is English Version of my JP's.

Sorry if my English sentences are incorrect.

designetwork