I am working on a project that requires reading data from this terrible API that responds with terrible structured JSON data:
"finn-contanct": {...}
"finn-adata": {
"#attributes": {
"model": "https://cache.api.finn.no/iad/ad/model/car-used-sale"
},
"finn-field": [
{
"#attributes": {
"name": "authorized_dealership",
"value": "true"
}
},
{
"#attributes": {
"name": "body_type",
"value": "Stasjonsvogn"
}
},
{
"#attributes": {
"name": "car_location",
"value": "Norge"
}
},
{
"#attributes": {
"name": "engine"
},
"finn-field": [
{
"#attributes": {
"name": "effect",
"value": "90"
}
},
{
"#attributes": {
"name": "fuel",
"value": "Diesel"
}
}
]
},
{...},
]
}
How can i dynamically get the values under each attribute based on the siblings name value? Ideally with a function that accepts one parameter that finds the value in there by providing a key corresponding to the value i'm looking for.
Here is an example of what i'm expecting:
Given a function that expects one parameter: getAttrValue('key') I want to get the value under the #attributes sibling. So if I use the function like this: getAttrValue('body_type') i'm simply expecting this back: Stasjonsvogn. I don't really care about nested items. So if I do this: getAttrValue('fuel') I'm simply expecting: Diesel
I found this answer here on SO. But the problem with that method is that it doesn't work well with nested items. So does anyone have a method that would work with the data-structure I got above here?
The response is a total mess and I don't know how to handle it, nor how to Google it properly. So any help would be appreciated greatly.
Collect attributes into associative array recursively:
function collectAttributes($data)
{
$attributes = [];
$nodeAttribute = isset($data['#attributes']) ? $data['#attributes'] : [];
//collect current node attribute value
if (isset($nodeAttribute['name'])) {
$attributes[$nodeAttribute['name']] = isset($nodeAttribute['value']) ? $nodeAttribute['value'] : '';
}
//collect nested attributes recursively
foreach ($data as $nestedNode) {
if (is_array($nestedNode)) {
$attributes = array_merge($attributes, collectAttributes($nestedNode));
}
}
return $attributes;
}
And then use result as simple associative array:
$data = json_decode($inputJson, true);
$atttributes = collectAttributes($data);
echo $attributes['fuel']; //don't forget isset checking if you are not sure about content
But if you have attributes with same name you'll see only latest this way.
Related
Assume that I have below json response fetched from an API.
{
"owner": "Jane Doe",
"pets": [
{
"color": "white",
"type": "cat"
},
{
"color": "black",
"type": "dog"
}
]
}
From the below PHP code I have converted the json string into a json object. And displayed the pet types.
$jsonObject = json_decode($json);
foreach($jsonObject->pets as $pets){
echo 'Pet type:'.$pets->type.'</br>';
}
However in some cases the response json from the API is in below format
{
"owner": "John Doe",
"pets": {
"color": "white",
"type": "cat"
}
}
in this case above php foreach iteration fails with below message
*Notice: Trying to get property of non-object *
I'm looking for a easy way to do this because the actual json response which i'm handling has lot of these occurrences.
You need to check whether $jsonObject->pets is an array or object. If it's an object, replace it with an array containing that object, then the loop will work.
if (!is_array($jsonObject->pets)) {
$jsonObject->pets = array($jsonObject->pets);
}
You could also do it with a conditional in the foreach:
foreach (is_array($jsonObject->pets) ? $jsonObject->pets : [jsonObject->pets] as $pet) {
...
}
If you don't want to have to write all that every time, you could put it in a function:
function as_array($x) {
return is_array($x) ? $x : [x];
}
and then use:
foreach (as_array($jsonObject->pets) as $pet) {
...
}
I'd also complain to the API designer. It's ridiculous to return inconsistent data formats like this.
I'm working on my task right now, which accessing specific array when it is called by front end.
My example data is like this
{
"data": [
{
"name": "Jon Snow",
"id": "01-0001",
},
{
"name": "Robert Stark",
"id": "01-0002"
},
{
"name": "Sansa Stark",
"id": "01-002333"
},
{
"name": "Arya Stark",
"id": "01-00012"
},
{
"name": "Bran Stark",
"id": "01-0003"
},
{
"name": "Rickon Stark",
"id": "01-0005"
}
]
}
* In my front end I have this code *
selectedEmployee: any=null;
setActiveEmployee(employee: any) {
this.selectedEmployee = employee;
let myJSON = JSON.stringify(this.selectedEmployee);
this.perEmpLateEarly();
}
Whenever I choose the employee i get the id of that employee.
So in this, if i choose "id": "01-0001" it will return the first array and it will keep the rest, and if I choose "id": "01-0002" it will return the second one and will keep the rest and so on. How can I do that in Php?
Thanks in advance
You will do a GET/POST HTTP request from frontend, which would look something like this in
your_backend_page.php?id=<ID HERE>
Then the "your_backend_page.php" would look like as follows:
$list = { "data": [ { .... }, { ... }] } // this is the array you have
$idFromFrontEnd = $_GET["id"];
foreach ($list["data"] as $item) { // iterate over all items
if ($item["id"] == $idFromFrontEnd) { // check if id matches
echo json_decode($item); // if matches, print this item
}
}
Please note this approach is okay if you have a small number of items. For a larger list, you might want to have a database, where you can use sql to select.
I'm parsing a JSON file in PHP and ran into some issues with a data structure that I can't figure out how to make sense of. This is what one data node looks like:
{
"data": [{
"title": "Some title",
"subtitle": "Some subtitle",
"description": "Some description",
"labels": [{
"type": "itemId",
"raw": "someId12345"
}, {
"type": "itemtype",
"raw": "general"
}]
}]
}
This is the very basic code I'm using:
$url = 'data.json';
$content = file_get_contents($url);
$json = json_decode($content, true);
foreach($json['data'] as $item) {
return $item['title'];
return $item['description'];
}
Getting the title and description works, but I'm struggling with those labels. I would like to get the "raw" value for the type itemId (ie. someId12345) but I can't figure out how. The labels aren't in a fixed order, otherwise I could just use something like this to get the ID:
return $item['labels'][0]['raw'];
I tried creating a separate foreach but that only gives me an unidentified index on all values.
foreach($json['data'] as $ID) {
if($ID['labels']['itemId'] == $_GET['labels']['itemId']) {
return $ID['raw'];
break;
}
}
How can I get the sibling value so I'd end up with this data:
Some title
Some description
someId12345
It isn't different from what you're already doing:
foreach ($json['data'] as $item) {
foreach ($item['labels'] as $label) {
var_dump($label['raw']);
}
}
Demo
To filter by type you can use an if construct:
if ($label['type'] === 'itemId') {
var_dump($label['raw']);
}
I have the following deocoded JSON array.
I need to access the "type" inside the context, as well as I need to loop through each of the values in the payload. How do I do that?
{
"RequestHeader":
{
"mess": "am putting it on my wall....",
"created_time": "2010-08-24T09:01:25+0000"
},
"context" :
{
"type": "friends,circles"
}
"payload" [ {12345},{12345} ,{2345} ]
}
I tried the following, but it doesn't work
$decoded = json_decode($json_string);
for ($i=0;$i<payload.length;++$i)
{
$id=$decoded->payload[$i];
//do some operation with the id
}
First of all the JSON you provided is invalid. Supposedly the valid one should look like this
{
"RequestHeader": {
"mess": "am putting it on my wall....",
"created_time": "2010-08-24T09:01:25+0000"
},
"context": {
"type": "friends,circles"
},
"payload": [
12345,
12345,
2345
]
}
After you've fixed the problem with JSON provider it will be quite easy to access data
<?php
$json = <<<'JSON'
{
"RequestHeader": {
"mess": "am putting it on my wall....",
"created_time": "2010-08-24T09:01:25+0000"
},
"context": {
"type": "friends,circles"
},
"payload": [
12345,
12345,
2345
]
}
JSON;
$data = json_decode($json, true);
$type = $data['context']['type'];
var_dump($type);
foreach($data['payload'] as $id) {
var_dump($id);
}
Remember to make sure you check that the data actually exists before accessing it, e.g. isset($data['context']['type']) unless you are absolutely sure in it's integrity.
When you use json_decode method, the output will be nested arrays
So for example to access context type you need to do the following
echo $decoded["context"]["type"];
And to loop on payload you need to do the following
for ($i=0;$i<$decoded["payload"].length;++$i)
{
$id=$decoded["payload"][$i];
//do some operation with the id
}
I really need help on this one.
I have the following Json Schema:
{
"url": "http://www.google.com",
"bodySchema": {
"type": "object",
"properties": {
"SKU": {
"sync": "True",
"mapTo": "SKU",
"type": "string"
},
"WareHouseId": {
"sync": "False",
"mapTo": "",
"type": "integer"
},
"Stock": {
"sync": "True",
"mapTo": "Stock",
"type": "integer"
}
},
"required": {
"0": "SKU",
"1": "Stock"
}
}
}
I would like to retrieve all elements and check if they are required or not,
On the first part (Getting all elements)
What I'm doing is:
foreach ($this->methods as $data) {
if(!empty($data['bodySchema']->properties)){
}
}
But my problem is that I have no way to get the SKU, WarehouseID or Stock, because it's not a key nor anything of the kind.
For my second issue what I was thinking, was to put all required as string and do a loop through them, but if there is any alternative would be glad to know.
You can get the properties out with a simple loop:
foreach ($data->bodySchema->properties as $key => $value) {
// ..
}
If you want to add the required field to the results from above, you can do it like so:
foreach ($data->bodySchema->required as $required) {
$data->bodySchema->properties->$required->required = true;
}
Example with objects or with arrays.