Customizing JSON output CakePHP - json

$user = $this->User->find( 'all' );
$this->set( 'users', $user );
I have this code in my controller.
In my view I have this.
echo json_encode( compact( 'users' ) );
It outputs json like this
{
"users": [{
"User": {
"user_id": "2",
"email": "email#test.com",
"name": "Blah"
}]
}
}
Is there anyway to format this to remove the entire array wrapped in "users", and also remove every object being a member of "User".
This makes it harder to use on the front end. I'd like it to look like this.
[{
"user_id": "2",
"email": "email#test.com",
"name": "Blah"
}]
Thanks for any help.

I don't fully understand what you mean by "remove the entire array wrapped in "users"" and "remove every object being a member of "User"", but according to your desired output format example, you'll need to extract and pass the exact data that you want to be encoded to json_encode, instead of passing everything using compact.
Extracting could be done with the Set or the Hash class (depending on your Cake version)
Assuming your model returns the data in the default CakePHP format, this for example:
json_encode(Set::extract('/User/.', $users));
should give you a structure like this:
[{
"user_id": "2",
"email": "email#test.com",
"name": "Blah"
}]
and with multiple users it should look like this
[{
"user_id": "1",
"email": "foo#test.com",
"name": "Bar"
},
{
"user_id": "2",
"email": "email#test.com",
"name": "Blah"
}]

Use like this:
$users= (Set::extract('/User/.', $users));
pr($users);
It will remove Model from result Array and then json_encode or whatever further usage.
More library functions Set class Here and Hash class Here

Related

Retrieve specific value from a JSON blob in MS SQL Server, using a property value?

In my DB I have a column storing JSON. The JSON looks like this:
{
"views": [
{
"id": "1",
"sections": [
{
"id": "1",
"isToggleActive": false,
"components": [
{
"id": "1",
"values": [
"02/24/2021"
]
},
{
"id": "2",
"values": []
},
{
"id": "3",
"values": [
"5393",
"02/26/2021 - Weekly"
]
},
{
"id": "5",
"values": [
""
]
}
]
}
]
}
]
}
I want to create a migration script that will extract a value from this JSON and store them in its own column.
In the JSON above, in that components array, I want to extract the second value from the component with an ID of "3" (among other things, but this is a good example). So, I want to extract the value "02/26/2021 - Weekly" to store in its own column.
I was looking at the JSON_VALUE docs, but I only see examples for specifing indexes for the json properties. I can't figure out what kind of json path I'd need. Is this even possible to do with JSON_VALUE?
EDIT: To clarify, the views and sections components can have static array indexes, so I can use views[0].sections[0] for them. Currently, this is all I have with my SQL query:
SELECT
*
FROM OPENJSON(#jsonInfo, '$.views[0].sections[0]')
You need to use OPENJSON to break out the inner array, then filter it with a WHERE and finally select the correct value with JSON_VALUE
SELECT
JSON_VALUE(components.value, '$.values[1]')
FROM OPENJSON (#jsonInfo, '$.views[0].sections[0].components') components
WHERE JSON_VALUE(components.value, '$.id') = '3'

json object format for user data api

I have made an API that serves user data as a json file (e.g. name, userId...). The idea is that when someone logs in, their user ID loads the user data specific to them. I am not sure if I am supposed to create 'users' as an array or as an object. An array is more elegant, but if 'users' is an object I can pick out the right 'user' object with a key-value pair, where the key is the user ID.
How do I find the right user if I use an array?
Which way is proper JSON?
{
"users": {
"1": {
"userId": "1",
"displayname": "Fred"
},
"2": {
"userId": "2",
"displayname": "Ben"
},
"3": {
"userId": "3",
"displayname": "Sarah"
}
}
}
or
{
"users": [
{
"userId": "1",
"displayname": "Fred"
},
{
"userId": "2",
"displayname": "Ben"
},
{
"userId": "3",
"displayname": "Sarah"
}
]
}
Always try to keep the keys in the JSON constant rather than making them dynamic. Dynamic keys are complex to parse on the client side. You can always include the info about the dynamic key also inside a object with some fixed key.
Use an array as in the second listing.
Its up to the client to create an object from the array if it needs one.

How to index multidimensional arrays in couchdb

I have a multidimensional array that I want to index with CouchDB (really using Cloudant). I have users which have a list of the teams that they belong to. I want to search to find every member of that team. So, get me all the User objects that have a team object with id 79d25d41d991890350af672e0b76faed. I tried to make a json index on "Teams.id", but it didn't work because it isn't a straight array but a multidimensional array.
User
{
"_id": "683be6c086381d3edc8905dc9e948da8",
"_rev": "238-963e54ab838935f82f54e834f501dd99",
"type": "Feature",
"Kind": "Profile",
"Email": "gc#gmail.com",
"FirstName": "George",
"LastName": "Castanza",
"Teams": [
{
"id": "79d25d41d991890350af672e0b76faed",
"name": "First Team",
"level": "123"
},
{
"id": "e500c1bf691b9cfc99f05634da80b6d1",
"name": "Second Team Name",
"level": ""
},
{
"id": "4645e8a4958421f7d843d9b34c4cd9fe",
"name": "Third Team Name",
"level": "123"
}
],
"LastTeam": "79d25d41d991890350af672e0b76faed"
}
This is a lot like my response at Cloudant Selector Query but here's the deal, applied to your question:
The easiest way to run this query is using "Cloudant Query" (or "Mango", as it's called in the forthcoming CouchDB 2.0 release) -- and not the traditional MapReduce view indexing system in CouchDB. (This blog covers the differences: https://cloudant.com/blog/mango-json-vs-text-indexes/ and this one is an overview: https://developer.ibm.com/clouddataservices/2015/11/24/cloudant-query-json-index-arrays/).
Here's what your CQ index should look like:
{
"index": {
"fields": [
{"name": "Teams.[].id", "type": "string"}
]
},
"type": "text"
}
And what the subsequent query looks like:
{
"selector": {
"Teams": {"$elemMatch": {"id": "79d25d41d991890350af672e0b76faed"}}
},
"fields": [
"_id",
"FirstName",
"LastName"
]
}
You can try it yourself in the "Query" section of the Cloudant dashboard or via curl with something like this:
curl -H "Content-Type: application/json" -X POST -d '{"selector":{"Teams":{"$elemMatch":{"id":"79d25d41d991890350af672e0b76faed"}}},"fields":["_id","FirstName","LastName"]}' https://broberg.cloudant.com/teams_test/_find
That database is world-readable, so you can see the sample documents I created in there here: https://broberg.cloudant.com/teams_test/_all_docs?include_docs=true
Dig the Seinfeld theme :D
You simply need to loop through the Teams array and emit a view entry for each of the teams.
function (doc) {
if(doc.Kind === "Profile"){
for (var i=0; i<doc.Teams.length; i++) {
var team = doc.Teams[i];
emit(team.id, [doc.FirstName, doc.LastName]);
}
}
}
You can then query for all profiles with a specific team id by keying on the team id like this
.../view?key="79d25d41d991890350af672e0b76faed"
giving
{"total_rows":7,"offset":2,"rows":[
{"id":"0d15041f43b43ae07e8faa737f00032c","key":"79d25d41d991890350af672e0b76faed","value":["Adam","Alpha"]},
{"id":"68779729be3610fd8b52b22574000ae8","key":"79d25d41d991890350af672e0b76faed","value":["Bob","Bravo"]},
{"id":"9f97f1565f03aebae9ca73e207001ee1","key":"79d25d41d991890350af672e0b76faed","value":["Chuck","Charlie"]}
]}
or you can include the actual profiles in the result by adding &include_docs=true to the query.

jqGrid JSON notation on objects

there!
I´ve one column in my jqGrid that is empty.
But i checked the object on chrome console and thats fine.
colModel definition
colModel:[
{name:'id',index:'id', width:55,editable:false,editoptions:{readonly:true,size:10},hidden:true},
{name:'firstName',index:'firstName', width:100,searchoptions: { sopt: ['eq', 'ne', 'cn']}},
{name:'lastName',index:'lastName', width:100,editable:true, editrules:{required:true}, editoptions:{size:10}},
{name:'books[0].nome',index:'books[0].nome', width:100,editable:true, editrules:{required:true}, editoptions:{size:10}},
{"formatter":"myfunction", formatoptions:{baseLinkUrl:'/demo/{firstName}|view-icon'}}
]
JSON response
{
"total": "10",
"page": "1",
"records": "3",
"rows": [
{
"id": 1,
"firstName": "John",
"lastName": "Smith",
"books": [{"nome": "HeadFirst"}]
},
{
"id": 2,
"firstName": "Jane",
"lastName": "Adams",
"books": [{"nome": "DalaiLama"}]
},
{
"id": 35,
"firstName": "Jeff",
"lastName": "Mayer",
"books": [{"nome": "Bobymarley"}]
}
]
}
chrome console inspect object
rowdata.books[0].nome
"HeadFirst"
Any one know where theres are possibles trick?
Tks!
You should use as the value of name property of colModel only the names which can be used as property name in JavaScript and as CSS id names. So the usage of name:'books[0].nome' is not good idea.
To solve your problem you can use jsonmap. For example you can use dotted name conversion:
{name: 'nome', jsonmap: 'books.0.nome', ...
In more complex cases you can use functions as the value of jsonmap. For example
{name: 'nome', jsonmap: function (item) {
return item.books[0].nome;
}, ...
You can find some more code examples about the usage of jsonmap in other old answers: here, here, here, here, here.
name is intended to be a unique name for the row, not a reference to a JSON object. From the jqGrid colModel options documentation:
Set the unique name in the grid for the column. This property is required. As well as other words used as property/event names, the reserved words (which cannot be used for names) include subgrid, cb and rn.
You can also observe how .name is used within grid.base.js - for example:
var nm = {},
...
nm = $t.p.colModel[i].name;
...
res[nm] = $.unformat.call($t,this,{rowId:ind.id, colModel:$t.p.colModel[i]},i);
Anyway, to get back to your question I think you will have better luck by passing down the book name directly - as strings and not objects - and referencing it by name as something like bookName.

JSON Syntax: Transmitting an array

A valid JSON Syntax is something of the kind:
{
"username": "admin",
"password": "123"
}
But what if I want to transmit an array of 'users' (given the example), instead of a single 'user' ?
Is the code below Valid JSON, according to the specifications?
[{
"username": "admin",
"password": "123"
}, {
"username": "bbvb",
"password": "sdfsdf"
}, {
"username": "asd",
"password": "222"
}]
And if not, what is the best way to transmit an array of values across with JSON? (And with 'best way', I mean syntactically)
Yes, your example is valid JSON - that is exactly how you want to use an array.
Edit : Here is a good link on JSON and its usage.
The not-very-well-known page json.org has a diagram that shows the syntax. It’s extremely simple to understand, IMHO.
Json Syntax Includes following.
1. Data is represented in name/value pairs.
2. Each name is followed by ':'(colon).
3. The name/value pairs are separated by ,(comma).
4. Json object starts and ends with '{' and '}'.
5. Square brackets '[ ]' hold arrays and values are separated by
,(comma).
Json Objects Example
{
"id":"21",
"language": "Json",
"edition": "second",
}
Json Array Example
{
"book": [
{
"id":"21",
"language": "Json",
"edition": "second"
},
{
"id":"42",
"language": "Json",
"edition": "third"
}]
}
I have taken reference from http://www.tutsway.com/json-syntax.php
What you wrote up there is already correct :)
[{ "username" : "admin", "password" : "123" }, { "username" : "bbvb", "password" : "sdfsdf" }, { "username" : "asd", "password" : "222" }]