JSON-Path Combining Expression With Index - json

Given the following sample JSON where we will not always know the order...
{
"contacts": [
{
"id": 287997,
"type": "P",
"relationship": "Mother",
"firstName": "Sara",
"lastName": "Johnson"
},
{
"id": 300982,
"type": "EC",
"relationship": "Aunt",
"firstName": "Janet",
"lastName": "Smith"
},
{
"id": 287200,
"type": "P",
"relationship": "Father",
"firstName": "William",
"lastName": "Johnson"
},
{
"id": 287997,
"type": "EC",
"relationship": "Friend",
"firstName": "Harold",
"lastName": "Johnson"
}
]
}
I want to retrieve the first contact which is of type 'EC'. The following retrieves all 'EC' type contacts just fine...
$.contacts[?(#.type == 'EC')]
But, I want only the first EC contact. I tried...
$.contacts[?(#.type == 'EC')][0]
But this did not work. I tried a few other variations with no luck. I would like to be able to achieve this without going outside of the JSON-Path approach if possible.
I know I can combine expressions like this...
$.contacts[?(#.type == 'EC' && #.firstName == 'Janet')]
But, I need to get the first contact that matches the 'EC' expression. So, after the 'EC' expression is evaluated, get the first of the filtered contacts.
I appreciate any help I can get! Thanks!

Kevin - yesterday I released a JS-lib I've been working on (DefiantJS) that solves your problem exactly the way you want it, and with the standardised XPath instead of JSONPath. At this page, there is a tool I've written XPath evaluator.
http://www.defiantjs.com/#xpath_evaluator
By clicking "Edit", I have pasted your JSON structure, and clicked "Edit" again (so that the structure is parsed by the tool). Now, entering the XPath below will filter the selection you want:
//contacts[./type="EC"][1]
To put this in Javascript code:
var obj = {
"contacts": [
{
"id": 287997,
"type": "P",
"relationship": "Mother",
"firstName": "Sara",
"lastName": "Johnson"
},
{
"id": 300982,
"type": "EC",
"relationship": "Aunt",
"firstName": "Janet",
"lastName": "Smith"
},
{
"id": 287200,
"type": "P",
"relationship": "Father",
"firstName": "William",
"lastName": "Johnson"
},
{
"id": 287997,
"type": "EC",
"relationship": "Friend",
"firstName": "Harold",
"lastName": "Johnson"
}
]
};
var sel = JSON.search(obj, '//contacts[./type="EC"][1]');
// sel[0] will contain your filtered object
DefiantJS extends the global object with a new method; "search". Since the function "search" always returns an array of matching elements, the handle to your selection is "sel[0]". Another Xpath for selecting contacts with the lastName "Johnson" is:
//contacts[./lastName="Johnson"]
The XPath evaluator tool have example XPath as well - which is meant to ease in developers not familiar with XPath. The source code of DefiantJS can be found at Github:
https://github.com/hbi99/defiant.js

Related

Why is JSON being detected as empty?

So I have a JSON file I got from Postman which is returning as an empty object. This is how I'm reading it.
import regscooter from './json_files/reginald_griffin_scooter.json'
const scoot = regscooter;
const CustomerPage = () => {...}
reginald_griffin_scooter.json
{
"success": true,
"result": {
"id": "hhhhhhhhhh",
"model": "V1 Scooter",
"name": "hhhhhhhhhh",
"status": "active",
"availabilityStatus": "not-available",
"availabilityTrackingOn": true,
"serial": "hhhhhhhhhhhh",
"createdByUser": "hhhhhhhhK",
"createdByUsername": "hhhhhhhh",
"subAssets": [
"F0lOjWBAnG"
],
"parts": [
"hhhhhhhh"
],
"assignedCustomers": [
"hhhhhhhhh"
],
"createdAt": "2019-12-03T21:47:26.218Z",
"updatedAt": "2020-06-26T22:05:54.526Z",
"customFieldsAsset": [
{
"id": "hhhhhhh",
"name": "MAC",
"value": "hhhhhhhh",
"asset": "hhhhhhhhhh",
"user": "hhhhhhhhh",
"createdAt": "2019-12-03T21:47:26.342Z",
"updatedAt": "2019-12-11T16:29:24.732Z"
},
{
"id": "hhhhhhhh",
"name": "IMEI",
"value": "hhhhhhh",
"asset": "hhhhhhh",
"user": "hhhhhhhhhh",
"createdAt": "2019-12-03T21:47:26.342Z",
"updatedAt": "2019-12-11T16:29:24.834Z"
},
{
"id": "hhhhhhhhh",
"name": "Key Number",
"value": "NA",
"asset": "hhhhhhhhh",
"user": "hhhhhhhhhhh",
"createdAt": "2019-12-03T21:47:26.342Z",
"updatedAt": "2019-12-11T16:29:24.911Z"
}
]
}
}
The error is that "const scoot" is being shown as an empty object {}. I made sure to save a ton of times everywhere. I am able to read through the imported JSON file in other variables in similar ways, so I don't know why I can't parse this one. I just want to access the JSON object inside this. Also I omitted some information with hhhhh because of confidentiality.
EDIT: The code works, but it still has a red line beneath result when I do:
const scoot = regscooter.result.id;
It would be much more effective if you will provide an example in codesandbox or so.
However at first look it might be a parser issue ( maybe you are using Webpack with missing configuration for parsing files with json extension ), meaning we need more information to provide you with a full answer ( maybe solution ? ).
Have you tried to do the next:
const scoot = require('./json_files/reginald_griffin_scooter.json');

replace "key" name in whole JSON python for bulk data in efficient way

Actually i am pushing data to other system but before pushing i have to change the "key" in the whole JSON. JSON may contain 200 or 10000 or 250000 data.
sample JSON:
{
"insert": "table",
"contacts": [
{
"testName": "testname",
"ContactID": 212121
},
{
"testName": "testname",
"ContactID": 2146354564
},
{
"testName": "testname",
"ContactID": 12312
},
{
"testName": "testname",
"ContactID": 211221
},
{
"testName": "testname",
"ContactID": 10218550
}
]
}
I need to change contacts array Keys. These contacts may be in bulk. So i need to work with this efficiently with minimal complexity.
The above JSON to be converted as below
{
"insert": "table",
"contacts": [
{
"name": "testname",
"phone": 212121
},
{
"name": "testname",
"phone": 2146354564
},
{
"name": "testname",
"phone": 12312
},
{
"name": "testname",
"phone": 211221
},
{
"name": "testname",
"phone": 10218550
}
]
}
here is my code trying by loop
ini_dict = request.data
contact_data = ini_dict['contacts']
for i in contact_data:
i['name'] = i.pop('testName')
print(contact_data)
Please suggest me how can i change the key names efficiently for bulk data. i mean for 50000 lists in contacts. "for loop" will be leading a performance issue. So please let me know the efficient way to achieve this
I dont know how fast you need it to be nor how you are choosing to store your json. One simple solution is just store it as a string and then replace all the instances of your attributes.
# Something like this using a jsonstring
jsonstring.replace("'testName':", "'name':")
jsonstring.replace("'ContactId':", "'phone':")
If you want to do this in bulk you, may need to create some batch process to be able to fetch multiple existing records and make changes at once. I have done this before with the java equivalent of https://pypi.org/project/JayDeBeApi/ but, that was more for modifying existing records in a database.

Google json style guide: How to send single item response?

There is an items node in the specifications which says it is for an array of items, like paging items, youtube video list
What if I have GET request on a single item, how should the response be formatted ?
Just to one item in the array?
items:[item]
https://google.github.io/styleguide/jsoncstyleguide.xml
I don't think #tanmay_vijay's answer is correct or nuanced enough as it seems that single item responses are in arrays in the YouTube example in the docs.
{
"apiVersion": "2.0",
"data": {
"updated": "2010-02-04T19:29:54.001Z",
"totalItems": 6741,
"startIndex": 1,
"itemsPerPage": 1,
"items": [
{
"id": "BGODurRfVv4",
"uploaded": "2009-11-17T20:10:06.000Z",
"updated": "2010-02-04T06:25:57.000Z",
"uploader": "docchat",
"category": "Animals",
"title": "From service dog to SURFice dog",
"description": "Surf dog Ricochets inspirational video ...",
"tags": [
"Surf dog",
"dog surfing",
"dog",
"golden retriever",
],
"thumbnail": {
"default": "https://i.ytimg.com/vi/BGODurRfVv4/default.jpg",
"hqDefault": "https://i.ytimg.com/vi/BGODurRfVv4/hqdefault.jpg"
},
"player": {
"default": "https://www.youtube.com/watch?v=BGODurRfVv4&feature=youtube_gdata",
"mobile": "https://m.youtube.com/details?v=BGODurRfVv4"
},
"content": {
"1": "rtsp://v5.cache6.c.youtube.com/CiILENy73wIaGQn-Vl-0uoNjBBMYDSANFEgGUgZ2aWRlb3MM/0/0/0/video.3gp",
"5": "https://www.youtube.com/v/BGODurRfVv4?f=videos&app=youtube_gdata",
"6": "rtsp://v7.cache7.c.youtube.com/CiILENy73wIaGQn-Vl-0uoNjBBMYESARFEgGUgZ2aWRlb3MM/0/0/0/video.3gp"
},
"duration": 315,
"rating": 4.96,
"ratingCount": 2043,
"viewCount": 1781691,
"favoriteCount": 3363,
"commentCount": 1007,
"commentsAllowed": true
}
]
}
}
It could however be that it depends on the resource being targeted from the request. This is the way it is in the competing JSONAPI standard.
From JSONAPI standard:
A logical collection of resources MUST be represented as an array, even if it only contains one item or is empty.
You don't need to have items field for showing single item. If you're sure your API is always going to return single object, you can return it as data itself.
{
"data": {
"kind": "user",
"fields": "author,id",
"id": "bart",
"author": "Bart"
}
}
Fields such as data.kind data.fields data.etag data.id data.lang data.updated data.deleted can still be used here.
Source for snippet docs

Microsoft Flow: How to Concatenate Data from JSON Object

I have a REST Web Services Call that is returning data in the following format:
{
"Id": "0497cee4-45dc-47d8-97a8-b45ad8018775",
"Status": "OK",
"ProviderName": "MyApp",
"DateTimeUTC": "/Date(1508348383277)/",
"Contacts": [
{
"ContactID": "1efa0ea1-de5c-4172-869c-816e27c3c825",
"ContactStatus": "ACTIVE",
"Name": "Company",
"FirstName": "Joe",
"LastName": "Bob",
"EmailAddress": "mainguy#here.com",
"BankAccountDetails": "",
"ContactPersons": [
{
"FirstName": "Operations",
"LastName": "",
"EmailAddress": "there#here.com",
"IncludeInEmails": true
},
{
"FirstName": "Another",
"LastName": "Contact Email",
"EmailAddress": "here#there.com",
"IncludeInEmails": true
}
],
"HasAttachments": false,
}
]
}
Within Microsoft Flow I would like to grab the main contact email (Contacts.EmailAddress) as well as all of the secondary Contacts Emails (Contacts.ContactPersons[x].EmailAddress); and use that for the too field of down-flow email.
ContactPersons will not always be defined in every case, but Contacts.EmailAddress should be.
What is the best way to do this with a flow? Is there a way to concatenate data over a loop or something? I can't seem to find a way to do it.
Try using Data Operations (https://learn.microsoft.com/en-us/flow/data-operations).
You can start off with a Select, picking the EmailAddress field in the Map, and then redirecting that to a Join and using that output.

Adding brackets to json ajax

I'm working with a plugin called (http://michaeleisenbraun.com/columns/) that converts json to tables.
I use the following code:
<script>
$.ajax({
url:'/large-data.json',
dataType: 'json',
success: function(json) {
example2 = $('#example2').columns({
data:json,
});
}
});
</script>
It works well when the json is in brackets, like below:
[
{
"id": 9998,
"isActive": false,
"balance": "$5",
"age": 38,
"eyeColor": "blue",
"name": "Lola Townsend",
"gender": "female",
"company": "...",
"email": "asdf#asdf.com,
"phone": "..."
}
]
But, does not work if the json is not in brackets, like below:
{
"id": 9998,
"isActive": false,
"balance": "$5",
"age": 38,
"eyeColor": "blue",
"name": "Lola Townsend",
"gender": "female",
"company": "...",
"email": "asdf#asdf.com,
"phone": "..."
}
The json response is from other sites, so I will not be able to control whether it does / does not have brackets.
Is there a way to ensure the json returned has brackets each time and if not, that brackets are added?
I tried JSON.parse() and it did not work.
The first one mean it's an array object, the second one is only an object. I don't really get what you are trying to do right now but you can simply ass the object into in array if it's not allready one. something like :
if(!Arrays.isArray(yourObject)) {
var temp = [] ;
temp.push(yourObject);
yourObject= temp;
}
I haven't test it since i don't know what you want to do, but this is the main idea.
Hope it helps !
Nic
You can use regex to check if the code is correct with ^\[|\n*\]$. You should have 2 matches if the first character of the string is [ and the last is ].
You can test here : https://regex101.com/r/Cukwog/1