JSONPath Export Key & Value - jsonpath

I am using JSONPath to filter out a json file, I am trying to retrieve both the Key + Value from the JSON array but I am lost at figuring how best to do this.
QUERY
$.phoneNumbers[*].[type,number]
ARRAY
{
"firstName": "John",
"lastName" : "doe",
"age" : 26,
"address" : {
"streetAddress": "naist street",
"city" : "Nara",
"postalCode" : "630-0192"
},
"phoneNumbers": [
{
"type" : "iPhone",
"number": "0123-4567-8888",
"address" : {
"streetAddress": "naist street",
"city" : "Nara",
"postalCode" : "630-0192"
}
},
{
"type" : "home",
"number": "0123-4567-8910",
"address" : {
"streetAddress": "naist street",
"city" : "Nara",
"postalCode" : "630-0192"
}
}
]
}
CURRENT OUTPUT
[
"iPhone",
"0123-4567-8888",
"home",
"0123-4567-8910"
]
Desired Outcome
[
{
"type" : "iPhone",
"number": "0123-4567-8888",
},
{
"type" : "home",
"number": "0123-4567-8910",
}
]

What you're looking for can't be done with JSON Path because you're looking to transform the data. JSON path is only going to give you the values in a flat list.
You might find some luck with JMES Path. It's pretty similar, but I'm less familiar with it.

You likely need to add quotes
$.phoneNumbers[*].['type','number']

Related

Using JSONPath to filter and get only specific properties as result?

Is it possible to use JSONPath to both filter and "select" properties to keep for the result.
For instance if we have the following JSON:
{
"firstName": "John",
"lastName": "doe",
"age": 26,
"address": {
"streetAddress": "naist street",
"city": "Nara",
"postalCode": "630-0192"
},
"phoneNumbers": [
{
"type": "iPhone",
"number": "0123-4567-8888"
},
{
"type": "home",
"number": "0123-4567-8910"
}
]
}
And we run a JSONPath like:
$.phoneNumbers[?(#.type=='iPhone')]
We would end up with the result:
[
{
"type": "iPhone",
"number": "0123-4567-8888"
}
]
Now lets say that what I actually want is the phonenumber.. so we could do this:
$.phoneNumbers[?(#.type=='iPhone')].number
Which would result in:
[
"0123-4567-8888"
]
However.. the result that I would like to get would be:
[
{
"number": "0123-4567-8888"
}
]
Notice how the actual JSON-object is returned and the property..
Is that possible to achive somehow using JSONPath?
Since you know what property you're looking for (i.e. number), what you can do is to construct a new Json object with the property name and the returned value.
The actual implementation depends on what programming language you're using, but the pseudocode should look somewhat like this:
returnedList = json.find("$.phoneNumbers[?(#.type=='iPhone')].number")
initialize newJsonArray
foreach(returnedValue in returnedList):
newJsonArray.add(newJsonObject("number", returnedValue))
An alternative way to tackle the problem in OOP languages is to use lambda functions to filter your Json objects instead of using Jsonpath filters. An example on how to do it in C# using Newtonsoft.Json:
JArray jArray = new JArray(jObject.SelectToken("$.phoneNumbers").Where(x => x["type"].ToString() == "iPhone"));

Best way to get list of state-level places (google places api)

I'm currently working a project with the requirement to get a list of state-level places. I've tried the following two APIs but none of them can 100% meet the requirement:
Google Autocomplete API. In order to get rid off the detailed street-level places I passed types: ["(regions)"] which is OK from business' point of view (even though only state-level would be perfect, but city-level is still OK). However when user search for Washington, USA the API only returns 5 cities named Washington, and user have to search for WA, USA instead.
Google Places API. This API can successfully handle the Washington case above. However I couldn't find a way to restrict the API to get rid off the street-level places, unless I filter the returned places by the types attribute.
Does anyone know what is the best API to use for this scenario?
Doing a Text Search request with the search string as Washington, USA I get only 1 result which seems to be the WA state.
Request (use your own API key): https://maps.googleapis.com/maps/api/place/textsearch/json?query=Washington%2C%20USA&language=en&key=YOUR_API_KEY
Result:
{
"html_attributions" : [],
"results" : [
{
"formatted_address" : "Washington, USA",
"geometry" : {
"location" : {
"lat" : 47.7510741,
"lng" : -120.7401385
},
"viewport" : {
"northeast" : {
"lat" : 49.0024442,
"lng" : -116.91558
},
"southwest" : {
"lat" : 45.543541,
"lng" : -124.8489739
}
}
},
"icon" : "https://maps.gstatic.com/mapfiles/place_api/icons/v1/png_71/geocode-71.png",
"name" : "Washington",
"photos" : [
{
"height" : 2124,
"html_attributions" : [
"\u003ca href=\"https://maps.google.com/maps/contrib/101488181553592859672\"\u003eArko Bhattacharjee\u003c/a\u003e"
],
"photo_reference" : "ATtYBwLa-P4aH5Uh3rD2CKaZmwb8HyNPWZ1WZUnw_y4iaUouh4B6BKOwAo52kkiBNSfn3MJmkW6Ju50H_e7zhxs5m5oBJva-dywtTv2cF_OgX6COeUfnre_SVmXw1qA4Fof924hSOvutwFnjsO6MJ1R71ozhBfieWrtvN9dSwVbgQbvMu-3y",
"width" : 1440
}
],
"place_id" : "ChIJ-bDD5__lhVQRuvNfbGh4QpQ",
"reference" : "ChIJ-bDD5__lhVQRuvNfbGh4QpQ",
"types" : [ "administrative_area_level_1", "political" ]
}
],
"status" : "OK"
}
Double check this by doing a Place Details request with the returned place id ChIJ-bDD5__lhVQRuvNfbGh4QpQ:
Request (use your own API key): https://maps.googleapis.com/maps/api/place/details/json?place_id=ChIJ-bDD5__lhVQRuvNfbGh4QpQ&language=en&key=YOUR_API_KEY
Result:
{
"html_attributions" : [],
"result" : {
"address_components" : [
{
"long_name" : "Washington",
"short_name" : "WA",
"types" : [ "administrative_area_level_1", "political" ]
},
{
"long_name" : "United States",
"short_name" : "US",
"types" : [ "country", "political" ]
}
],
"adr_address" : "\u003cspan class=\"region\"\u003eWashington\u003c/span\u003e, \u003cspan class=\"country-name\"\u003eUSA\u003c/span\u003e",
"formatted_address" : "Washington, USA",
"geometry" : {
"location" : {
"lat" : 47.7510741,
"lng" : -120.7401386
},
"viewport" : {
"northeast" : {
"lat" : 49.00256875707851,
"lng" : -116.9155800245149
},
"southwest" : {
"lat" : 45.54354101516995,
"lng" : -124.8489739457119
}
}
},
"icon" : "https://maps.gstatic.com/mapfiles/place_api/icons/v1/png_71/geocode-71.png",
"name" : "Washington",
"photos" : [],
"place_id" : "ChIJ-bDD5__lhVQRuvNfbGh4QpQ",
"reference" : "ChIJ-bDD5__lhVQRuvNfbGh4QpQ",
"types" : [ "administrative_area_level_1", "political" ],
"url" : "https://maps.google.com/?q=Washington,+USA&ftid=0x5485e5ffe7c3b0f9:0x944278686c5ff3ba",
"utc_offset" : -480,
"website" : "http://www.access.wa.gov/"
},
"status" : "OK"
}

Can't write to Firebase database using rules

I'm trying to create a rule that allows some users to write but not all.
I need that all user can read 'menu' items but only users listed at store data can write.
My data structure:
{
"category" : [ null, "Burger", "Drinks" ],
"menu" : [ null, {
"available" : true,
"category" : "1",
"description" : "item1 description",
"image" : "chicken_maharaja",
"name" : "New Chicken Maharaja",
"price" : 1300,
"store" : 1
}, {
"available" : true,
"category" : "1",
"description" : "item2 description",
"image" : "big_spicy_chicken_wrap",
"name" : "Big Spicy Chicken Wrap",
"price" : 120,
"store" : 1
}, {
"available" : true,
"category" : "2",
"description" : "item3 description",
"image" : "thumsup",
"name" : "Thumsup 100ml",
"price" : 40,
"store" : 1
}, {
"available" : true,
"category" : "2",
"description" : "item4 description",
"image" : "mccafe_ice_coffee",
"name" : "Ice Coffee",
"price" : 140,
"store" : 1
}, {
"available" : true,
"category" : "1",
"description" : "item5 description",
"image" : "mc_chicken",
"name" : "MC Chicken",
"price" : 190,
"store" : 1
}, {
"available" : true,
"category" : "2",
"description" : "item6 description",
"image" : "Smoothie",
"name" : "Smoothie",
"price" : 70,
"store" : 2
}, {
"available" : true,
"category" : "1",
"description" : "item8 description",
"image" : "salad_wrap",
"name" : "Salad Wrap",
"price" : 150,
"store" : 2
} ],
"stores" : [ null, {
"location" : "Campinas - Taquaral",
"name" : "Store 1",
"user" : {
"pyixsRTw9qdiuESt62YnmEYXQt13" : true
}
}, {
"location" : "São Paulo - Perdises",
"name" : "Store 2",
"user" : {
"LBNZ8Dwp2rdJtlSh0NC1ApdtbAl2" : true,
"TLomOgrd3gbjDdpDAqGiwl0lBhn2" : true
}
} ],
"userProfile" : {
"LBNZ8Dwp2rdJtlSh0NC1ApdtbAl2" : {
"birthDate" : "1974-02-10",
"email" : "asd#asd.com",
"firstName" : "João",
"lastName" : "Silva"
},
"pyixsRTw9qdiuESt62YnmEYXQt13" : {
"birthDate" : "1974-02-10",
"email" : "leandro.garcias#gmail.com",
"firstName" : "Leandro",
"lastName" : "Garcia"
}
}
}
My rule:
{
"rules": {
"menu": {
"$items": {
".read": "true",
".write": "root.child('stores').child('1').child(data.child('user').val()).hasChild(auth.uid)"
}
},
"stores": {
"$store": {
".read": "true",
".write": "root.child('stores').child('$store').child(data.child('user').val()).hasChild(auth.uid)"
}
}
}
}
The read is ok. :-) But I can't write.
Your newData doesn't have a child user so that check always fails. You probably mean:
"43268522": {
"menu": {
"$items": {
".read": "true",
".write": "root.child('stores').child('1').child('user').hasChild(auth.uid)"
}
}
You're probably looking for this rule:
".write": "
root.child('stores')
.child(newData.child('store').val())
.child('user')
.hasChild(auth.uid)"
So this uses the store property from the new data to look up if the current user is in the store they're trying to modify.
Unfortunately this rule won't work with your current data structure, since the value of store is a number, while the key of a store is a string: "1" !== 1.
The simplest solution is to store the store as a string, e.g.:
"store": "1"
You might want to consider that anyway, since you're now getting Firebase's array coercion, which is not helpful. For more on this see our blog post on Best Practices: Arrays in Firebase. I'd recommend storing stores using either push IDs, or simply prefixing them, e.g.
"stores": {
"store1": {
...
}
}

How to correct refer to according normalized entity data in Redux Reducer

All:
I am pretty new to redux reducer, most answers point to normalizr.js. Taking example like:
const blogPosts = [
{
id : "post1",
author : {username : "user1", name : "User 1"},
body : "......",
comments : [
{
id : "comment1",
author : {username : "user2", name : "User 2"},
comment : ".....",
},
{
id : "comment2",
author : {username : "user3", name : "User 3"},
comment : ".....",
}
]
},
{
id : "post2",
author : {username : "user2", name : "User 2"},
body : "......",
comments : [
{
id : "comment3",
author : {username : "user3", name : "User 3"},
comment : ".....",
},
{
id : "comment4",
author : {username : "user1", name : "User 1"},
comment : ".....",
},
{
id : "comment5",
author : {username : "user3", name : "User 3"},
comment : ".....",
}
]
}
// and repeat many times
]
I define schema as below:
var authorSchm = new schema.Entity("authors", {}, {idAttribute: "username"});
var commentSchm = new schema.Entity("comments", {author:authorSchm})
var commentList = [commentSchm];
var postSchm = new schema.Entity("posts", {author:authorSchm, comments:commentList});
var postList = [postSchm];
var normalizedData = normalize(blogPosts, postList);
console.log(JSON.stringify(normalizedData, null, 4));
And I get result like:
{
"entities": {
"authors": {
"user1": {
"username": "user1",
"name": "User 1"
},
"user2": {
"username": "user2",
"name": "User 2"
},
"user3": {
"username": "user3",
"name": "User 3"
}
},
"comments": {
"comment1": {
"id": "comment1",
"author": "user2",
"comment": "....."
},
"comment2": {
"id": "comment2",
"author": "user3",
"comment": "....."
},
"comment3": {
"id": "comment3",
"author": "user3",
"comment": "....."
},
"comment4": {
"id": "comment4",
"author": "user1",
"comment": "....."
},
"comment5": {
"id": "comment5",
"author": "user3",
"comment": "....."
}
},
"posts": {
"post1": {
"id": "post1",
"author": "user1",
"body": "......",
"comments": [
"comment1",
"comment2"
]
},
"post2": {
"id": "post2",
"author": "user2",
"body": "......",
"comments": [
"comment3",
"comment4",
"comment5"
]
}
}
},
"result": [
"post1",
"post2"
]
}
I wonder how do I use this normalized data in Redux reducer and combineReducers?
And how do I know which entity I should go to get next level data according to the reference string( for example: when I get "post1", how do I know I should go to posts entity to get post1 object and inside post1 object, how to do that for those comment1, comment2.. )
Any answer to this is going to be largely subjective and dependent on your specific application and use-case. For a generic and recommended approach, check out the official example. Here's what the combineReducers looks like.

Google Geocoder Lookup get postal code by country and city

i'm currently using Google Geocoder API to determine location data for my web service.
It's important for me to get the postal code for a given country and city, but it's look like that google is limiting the result.
Here's the API call:
http://maps.googleapis.com/maps/api/geocode/json?address=deutschland,+saarlouis&language=de&sensor=false
The result is like that:
{
"results" : [
{
"address_components" : [
{
"long_name" : "Saarlouis",
"short_name" : "Saarlouis",
"types" : [ "locality", "political" ]
},
{
"long_name" : "Landkreis Saarlouis",
"short_name" : "Landkreis Saarlouis",
"types" : [ "administrative_area_level_3", "political" ]
},
{
"long_name" : "Saarland",
"short_name" : "SL",
"types" : [ "administrative_area_level_1", "political" ]
},
{
"long_name" : "Deutschland",
"short_name" : "DE",
"types" : [ "country", "political" ]
}
],
"formatted_address" : "Saarlouis, Deutschland",
"geometry" : {
"bounds" : {
"northeast" : {
"lat" : 49.36187570,
"lng" : 6.815549499999999
},
"southwest" : {
"lat" : 49.26046930,
"lng" : 6.67501510
}
},
"location" : {
"lat" : 49.31346060,
"lng" : 6.752286499999999
},
"location_type" : "APPROXIMATE",
"viewport" : {
"northeast" : {
"lat" : 49.36187570,
"lng" : 6.815549499999999
},
"southwest" : {
"lat" : 49.26046930,
"lng" : 6.67501510
}
}
},
"types" : [ "locality", "political" ]
}
],
"status" : "OK"
}
Thx for help.
Regards
Geocoding does not give postcode. Goenames has a database for Germany. Other countries are also available.
The reason you don't get the postal code is the query is too broad. If you would add a street name to the query the result will contain a postal code. A solution to your problem if you don't have a street name or don't want to use it is to split the geocoding into two parts:
Step 1: Use the city to get the GPS coordinates
https://maps.googleapis.com/maps/api/geocode/json?address=amsterdam
Step 2: Use the the GPS coordidates to get the postal code
https://maps.googleapis.com/maps/api/geocode/json?latlng=52.3182742,4.7288558
(Note: Double of same question posted here, answered by MidnightMotion. Adding to make easier to lookup.
https://gis.stackexchange.com/questions/33966/google-geocoder-lookup-get-postal-code-by-country-and-city)

Resources