json_encode treats a single element array as object [duplicate] - php

This question already has answers here:
How to add square braces around subarray data inside of a json encoded string?
(3 answers)
Closed 6 months ago.
this is the json i have to produce
{
"email": "example#example.com",
"campaign": {
"campaignId": "p86zQ"
},
"customFieldValues": [
{
"customFieldId": "y8jnp",
"value": ["18-29"]
}
]
}
if i use
$data = [
"email" => $_POST['mail'],
"campaign" => [
"campaignId" => "4JIXJ"
],
"customFieldValues" => [
"customFieldId" => "y8jnp",
"value" => ["18-29"]
]
];
and i do json_encode($data)
value is an object, but it should be an array with a single element. Somehow json_encode treats it as an object. Can i force it to treat it as an array with a single element ?
Thanks in Advance
Adrian

At the moment, you have a single array with 2 elements, instead of an array with a single element of a sub-array. In order to get the json in the first section, you need to add another array level.
$data = [
"email" => $_POST['mail'],
"campaign" => [
"campaignId" => "4JIXJ"
],
"customFieldValues" => [
[
"customFieldId" => "y8jnp",
"value" => ["18-29"]
]
]
];
That will give you this:
{
"email": null,
"campaign": {
"campaignId": "4JIXJ"
},
"customFieldValues": [
{
"customFieldId": "y8jnp",
"value": ["18-29"]
}
]
}

if there is one single element in the array the json_encode will treat is as an object and the key of the object is the index of the array
to treat it as an array you can use array_values(<your_array>)

Related

How to get a object value nested inside document in a collection in MongoDB PHP

I have stored a document set in MongoDB like below where ID is generated automatically through PHP
{
"_id": {
"$oid": "5ff745237d1b0000860007a6"
},
"user": "5ff741fb7d1b0000860007a4",
"name": "Test",
"slug": "fed73b70d080584c21e0a4353825ef91",
"category": "5fef4a467d1b000086000745",
"images": [{
"100x128": "test/year/month/image_da4181762396a31ff44f5ddc08ce6186.jpeg",
"200x256": "test/year/month/image_da4181762396a31ff44f5ddc08ce6186.jpeg",
"300x385": "test/year/month/image_da4181762396a31ff44f5ddc08ce6186.jpeg",
"500x642": "test/year/month/image_da4181762396a31ff44f5ddc08ce6186.jpeg"
},
{
"100x128": "test/year/month/image_da4181762396a31ff44f5ddc08ce6186.jpeg",
"200x256": "test/year/month/image_da4181762396a31ff44f5ddc08ce6186.jpeg",
"300x385": "test/year/month/image_da4181762396a31ff44f5ddc08ce6186.jpeg",
"500x642": "test/year/month/image_da4181762396a31ff44f5ddc08ce6186.jpeg"
}],
}
Now the problem is I want to get value from images object from key 100x128 only from the first array.
I am using the below code to achieve
$productsArray = $collection->aggregate(
[
[
'$match' => [
'user_id' => $user_id
]
],
[ '$unwind' => '$images' ],
[ '$unwind' => '$images.100x128' ],
[
'$project' => [
'name' => 1,
'image' => '$images'
]
]
]
);
and I always get an output as below
MongoDB\Model\BSONDocument Object
(
[storage:ArrayObject:private] => Array
(
[_id] => MongoDB\BSON\ObjectId Object
(
[oid] => 5ff745357d1b0000860007a7
)
[name] => Test 1
[image] => MongoDB\Model\BSONDocument Object
(
[storage:ArrayObject:private] => Array
(
[100x128] => test/year/month/image_da4181762396a31ff44f5ddc08ce6186.jpeg
[200x256] => test/year/month/image_da4181762396a31ff44f5ddc08ce6186.jpeg
[300x385] => test/year/month/image_da4181762396a31ff44f5ddc08ce6186.jpeg
[500x642] => test/year/month/image_da4181762396a31ff44f5ddc08ce6186.jpeg
)
)
)
)
I am not sure how to get just that specific value. Where am i going wrong here?
As far as i am getting your question it looks like you would need to understand the mongo concept. So you might get an array representation in UI or in PHP but at the end of day it is object.
Look closely the format that you have posted there is no array but multiple {} in that object just like JS so forget about array concept here.
If my understanding is correct this is what you are looking for
$productsArray = $collection->aggregate(
[
[
'$match' => [
'user_id' => $user_id
]
],
[ '$unwind' => '$images' ],
[ '$unwind' => '$images.100x128' ],
[
'$project' => [
'name' => 1,
'image' => '$images.100x128'
]
]
]
);
Whatever you have googled or used it is correct just you need to add the second unwind value i.e $images.100x128 instead of $images in the $project variable.
You can understand this way that $unwind variable uses recursive logic to get output as you want. Like let's say you have an array inside an array first it will get values from internal array then it will come to parent array and then so on. So the last value in $unwind variable should be used.
I am not sure if it will work on multiple objects but as you said you just need the first one. This should do the charm.

Convert to Array or Collection or List

I have a big chunk of data in this format:
[
{"date":"2018-11-17"},{"weather":"sunny"},{"Temp":"9"},
{"date":"2014-12-19"},{"Temp":"10"},{"weather":"rainy"},
{"date":"2018-04-10"},{"weather":"cloudy"},{"Temp":"15"},
{"date":"2017-01-28"},{"weather":"sunny"},{"Temp":"12"}
]
Is there any faster and more efficient way to organize and save it the database for future reference? Like making a comparison of the temperature for different days etc. [date,weather,Temp] are supposed to be in one set.
I've tried str_replace() but I'd like to know if there's any better way.
Taking into account your comment, it seems that is an array of objects in which every three objects make a record (that is form of: date, weather & temp) so you can create this setup with the help of collections:
$string = ['your', 'json', 'string'];
$records = collect(json_decode($string))
->chunk(3) // this creates a subset of every three items
->mapSpread(function ($date, $weather, $temp) { // this will map them
return array_merge((array) $date, (array) $weather, (array) $temp);
});
This will give you this output:
dd($records);
=> Illuminate\Support\Collection {#3465
all: [
[
"date" => "2018-11-17",
"weather" => "sunny",
"Temp" => "9",
],
[
"date" => "2014-12-19",
"Temp" => "10",
"weather" => "rainy",
],
[
"date" => "2018-04-10",
"weather" => "cloudy",
"Temp" => "15",
],
[
"date" => "2017-01-28",
"weather" => "sunny",
"Temp" => "12",
],
],
}
PS: To get the array version of this collections just attach ->all() at the end.
You can check in the Collections documentation a good explanation of the chunk() and mapSpread() methods as well of the rest of the available methods.

Fix invalid JSON [duplicate]

This question already has answers here:
How can I parse a JSON string in which objects are not comma separated?
(5 answers)
Closed 4 years ago.
I have a huge file that unfortunately contains invalid JSON.
It looks like list of arrays, not separated with a comma:
[{
"key": "value"
}]
[
[{
"key": "value",
"obj": {}
},
{}
]
]
[{
"key": "value",
"obj": {}
}]
The content inside every square brackets pair seems to be a valid JSON by itself.
The question is how to fix this JSON quickly with "search and replace"? (or any other method)
Tried many combinations including replacing "][" to "],[" and wrapping the whole file with one more square brackets pair making it array of arrays.
Every time it gives me invalid JSON.
Please help.
You can replace the closing brackets with '],' and wrap the entire string in brackets.
This snippet illustrates the method with the supplied sample data by applying the algorithm and then calling eval on the resulting string.
let jsonString = `[{
"key": "value"
}]
[
[{
"key": "value",
"obj": {}
},
{}
]
]
[{
"key": "value",
"obj": {}
}]`;
jsonString = jsonString.replace( /]/g, '],' );
jsonString = '[' + jsonString + ']';
myObject = eval( jsonString );
console.log( typeof myObject);
console.log( myObject.length );
console.log( myObject );
This is a dynamic php solution, but I would cringe to have to use this as a reliable source of data. This is a bandaid. Whatever code is producing this invalid json NEEDS to be fixed asap.
My regex pattern will seek all occurrences of ], zero or more spaces, then ] then it will add a comma after the ].
The entire string is wrapped in square brackets to make the json string valid.
The risk may or may not be obvious to all -- if any of the actual keys or values contain strings that qualify for replacement, then they will be damaged. This is why using regex on json is not recommended.
Code: (Demo)
$bad_json = '[{
"key": "value"
}]
[
[{
"key": "value",
"obj": {}
},
{}
]
]
[{
"key": "value",
"obj": {}
}]';
$valid_json = "[" . preg_replace("~]\K(?=\s*\[)~", ",", $bad_json) . "]";
var_export(json_decode($valid_json, true));
Output:
array (
0 =>
array (
0 =>
array (
'key' => 'value',
),
),
1 =>
array (
0 =>
array (
0 =>
array (
'key' => 'value',
'obj' =>
array (
),
),
1 =>
array (
),
),
),
2 =>
array (
0 =>
array (
'key' => 'value',
'obj' =>
array (
),
),
),
)

Convert PHP to JSON with Nested Array

I have a PHP variable I need to convert to JSON string.
I have following PHP code:
$username="admin";
$password="p4ssword";
$name="Administrator";
$email="myname#smsfree4all.com"
$params=compact('username', 'password','name','email', 'groups');
json_encode($params);
This works fine. But what I am not sure about is how do I encode the properties in PHP with nested key value pairs shown below:
{
"username": "admin",
"password": "p4ssword",
"name": "Administrator",
"email": "admin#example.com",
"properties": {
"property": [
{
"#key": "console.rows_per_page",
"#value": "user-summary=8"
},
{
"#key": "console.order",
"#value": "session-summary=1"
}
]
}
}
What is this with # before key value?
Something like this should do it
$username="admin"; //more variables
$params=compact('username' /* more variables to be compacted here*/);
$params["properties"] = [
"property" => [
[
"#key" => "console.rows_per_page",
"#value"=> "user-summary=8"
],
[
"#key"=> "console.order",
"#value"=> "session-summary=1"
]
]
];
echo json_encode($params);
The manual has more examples you can use
Notice that:
A key~value array is encoded into an object
A regular array (array of arrays here) is encoded into an array
Those are all the rules you need to consider to encode any arbitrary object
Something like this perhaps?
$properties = [
'property' => [
['#key' => 'console.rows_per_page', '#value' => 'user-summary=8'],
['#key' => 'console.order', '#value' => 'session-summary=1']
]
];
It's difficult to tell what you're asking.
You can nest in PHP using simple arrays, very similar to JavaScript objects:
$grandparent = array(
"person1" => array(
"name" => "Jeff",
"children" => array(
array("name" => "Matt"),
array("name" => "Bob")
)
),
"person2" => array(
"name" => "Dillan",
"children" => array()
)
);

JSON encode multiplies arrays as single array

$array = array(
$this->_order->revenue_seller($value,$from,$to),
$this->_order->refund_seller($value,$from,$to),
$this->_order->customers_seller($value,$from,$to),
$this->_order->sales_seller($value,$from,$to)
);
$this->response($array,200);
I want the data to be be displayed as a single array, but as we can see, the output is begin displayed as array of arrays:
[
[
{
"min_amount":"2.00",
"max_amount":"2.00",
"avg_amount":"2.000000",
"total_revenue":"2.00"
}
],
[
{
"total_refund_amount":"1.00"
}
],
[
{
"created_at":"2013-03-24 15:04:35"
}
],
[
{
"quantity":"1"
}
]
]
How can I make the data appear as one single array?
Like this:
[
{
"day":"2013-03-19",
"min_amount":"0.00",
"max_amount":"0.00",
"avg_amount":"0.000000",
"total_revenue":"0.00",
"quantity" : "1",
"total_refunded_amount":null,
"created_at":"2013-03-24 15:04:35"
}]
If you are getting array return by all four function than use array_merge as,
$array = array_merge($this->_order->revenue_seller($value,$from,$to),
$this->_order-refund_seller($value,$from,$to),
$this->_order->customers_seller($value,$from,$to),
$this-_order->sales_seller($value,$from,$to));
$this->response($array,200);
DEMO.

Categories