PHP - json_decode giving NULL - javascript

I'm trying to use the advice given in How to search through a JSON Array in PHP to lookup country names based on a country code in a .json file.
I have a file, countrycodes.js which is formatted like this:
countries = [
{code: "GB", name: "United Kingdom"},
{code: "AF", name: "Afghanistan"},
// ...
{code: "ZM", name: "Zambia"},
{code: "ZW", name: "Zimbabwe"}
];
The variable, countries has to be there because part of the application relies on this.
In PHP I've done the following:
$str = file_get_contents('countrycodes.js');
var_dump($str);
This outputs a string:
string(9642) "countries = [
{code: "GB", name: "United Kingdom"},
{code: "AF", name: "Afghanistan"},
// ...
However, when I try and json_decode it, the following gives NULL:
$str = file_get_contents('countrycodes.js');
$json = json_decode($str);
var_dump($json);
I don't know why this is because json_decode accepts a string, and this is what's given on the link I posted above? I tried removing the JavaScript variable (countries = ) but this made no difference.
Ultimately what I want to do is be able to give PHP a country code such as 'GB' and get it to return the appropriate name e.g. 'United Kingdom'. My understanding of this is the json_decode part will need to work before this is possible.
For reference, the reason countries = was being used is for populating a <select> element based on advice given here: Populating select using ajax json array

If you json_decode returns null, this means the input string is not in a valid format. Your file contains a javascript variable and not a JSON string.
This is how the string should probably formatted:
{
"countries": [
{"code": "GB", "name": "United Kingdom"},
{"code": "AF", "name": "Afghanistan"},
{"code": "ZM", "name": "Zambia"},
{"code": "ZW", "name": "Zimbabwe"}
]
}

Extending on Jerodev's answer, if you cannot will not change the representation, you could do the following.
Modify your file so that you wrap the keys with quotes. Something like,
countries = [
{"code": "GB", "name": "United Kingdom"},
{"code": "AF", "name": "Afghanistan"},
// ...
{"code": "ZM", "name": "Zambia"},
{"code": "ZW", "name": "Zimbabwe"}
];
And then just decode the json part.
$str = file_get_contents('countrycodes.js');
$str = substr($str,12, strlen($str)-13); // do not include the semicolon
var_dump(json_decode($str));
However this is not a good approach, so I'd still suggest to look for other ways to populate the data in your element.
Note that 12 is the position where [ starts, if you have made any changes to variable names or spaces, that (and 13) needs to change.

Related

JSON Format is off

The keys and values are separated in the Json object that I get from an api call. I have tried finding a solution It looks like the following:
{
"range": "'1'!A1:AM243",
"majorDimension": "ROWS",
"values":
[
"DeptID",
"DeptDescr",
"VP Area",
"VP Descr",
"HR Category",
"Employee Relations1",
"ER1Title",
"ER1Phone",
"ER1Email",
"Employee Relations2",
"ER2Title",
"ER2Phone",
"ER2Email",
"Compensation1",
"Comp1Title",
"Comp1Phone",
"Comp1Email",
"Compensation2",
"Comp2Title",
"Comp2Phone",
"Comp2Email",
"Employment1",
"E1Title",
"E1Phone",
"E1Email",
"Employment2",
"E2Title",
"E2Phone",
"E2Email",
"Employee Pay Services1",
"EPS1Title",
"EPS1Phone",
"EPS1Email",
"Employee Pay Services2",
"EPS2Title",
"EPS2Phone",
"EPS2Email"
],
[
"20734",
"Academic Success Centers",
"VES",
"VP Enroll Mgmt & Student Aff",
"Administrative",
"Brian Schmidt",
" Employee Relations Consultant",
"(928)523-6139",
"Brian.Schmidt#nau.edu",
"Marcia Warden",
"Assistant Director, Employee Relations",
"(928)523-9624",
"Marcia.Warden#nau.edu",
"Nicole Christian",
"Employment & Compensation Analyst",
"(928)523-6127",
" Nicole.Christian#nau.edu",
"Cathy Speirs",
"Associate Director",
"(928)523-6136",
"Cathy.Speirs#nau.edu",
"Nicole Christian",
"Employment & Compensation Analyst",
"(928)523-6127",
" Nicole.Christian#nau.edu",
"Cathy Speirs",
"Associate Director",
"(928)523-6136",
"Cathy.Speirs#nau.edu",
"Katherine Kurpierz",
"Payroll Specialist",
"(928)523-6129",
"Katherine.Kurpierz#nau.edu",
"Cheryl Brothers",
"Assistant Director - HR Payroll Services",
"(928)523-6085",
"Cheryl.Brothers#nau.edu"
], etc.
But I need it to look like:
[
{
"DeptID": 20734,
"DeptDescr": "Academic Success Centers",
"VP Area": "VES",
"VP Descr": "VP Enroll Mgmt & Student Aff",
"HR Category": "Administrative",
"Employee Relations1": "Brian Schmidt",
"Employee Relations2": "Marcia Warden",
"Compensation1": "Nicole Christian",
"Compensation2": "Cathy Speirs",
"Employment1": "Nicole Christian",
"Employment3": "Cathy Speirs",
"Employee Pay Services1": "Katherine Kurpierz",
"Employee Pay Services2": "Cheryl Brothers"
},etc
I am trying to use the data to populate a drop down using javascript and ajax. Any help is really appreciated.
The object your API returns is not a valid JSON. Was that API made by you or can you get that fixed somehow?
There are 2 things you could do to make it work
-One is change it to return exactly what you want;
-Two is to fix what it returns so that it is a valid JSON;
Going for what is wrong with the file you initially posted, let's remove the contents of the arrays so it's easier to spot the problem:
Your original data looks roughly like this:
{ "range": "'1'!A1:AM243",
"majorDimension": "ROWS",
"values": [],[]
}
To be valid you would need it to look like this:
{ "range": "'1'!A1:AM243",
"majorDimension": "ROWS",
"values": {
"keys": [],
"data": [],
}
}
Notice that I wrapped the two arrays of "values" with { } because it has to be an object if you want it to contain two arrays in it.
Then I gave each array a key with which you can call them. With that you'd be able to get what you want from your "values", so that for each item in the "keys" array you have something in that "data" array.
Hope this helps.
Well let's have a look;
Suppose this is a short version of the response data you got:
var res = `
{
"range": "'1'!A1:AM243",
"majorDimension": "ROWS",
"values": [
"DeptID",
"DeptDescr",
"VP Area"
],
[
"20734",
"Academic Success Centers",
"VES"
],
[
"345543",
"Academic Fails Centers",
"OK"
]
}
`;
As we can see by the first data, looks like a dump from a spreadsheet of sorts, and someone maybe scripted a way to export this data in a JSON-ish way. The values "Array" are the rows of this "spreadsheet".
We will clean it up, and get only the chunks that looks like ["value", "another value", "etc"]
// clean tabs and returns
res = res.replace(/\t/g, '').replace(/\n/g, '');
// get the array-ish chunks
rows = res.match(/\[(((["'])(?:(?=(\\?))\4.)*?\3),*)+\]/gm)
now let's make them real arrays:
var data = rows.map(function (row) {
return JSON.parse(row);
});
Now we have an array of arrays of strings. that means, an array of "rows" that contains the values of the "cells". The first one looks like the header row (the one with the names of the fields)
Lets make objects using each row of data except the first one. The first will serve us as the keys (we match the position (index) of the value from rows[n] from the value on rows[0] to get a key-value pair)
// Here we will define an object to store data
var data_object = { values: [] };
// for each row except the first
for(var i = 1; i < data.length; i++) {
var my_data = {};
//for each element of this row
for(var j = 0; j < data[i].length; j++) {
my_data[data[0][j]] = data[i][j];
}
data_object.values.push(my_data);
}
We have our object, let's suppose you need it in JSON format now:
var json_data = JSON.stringify(data_object);
// let's look what we have here
console.log('json_data:', json_data);
We will look at something like this as a result:
json_data: {"values":[{"DeptID":"20734","DeptDescr":"Academic Success Centers","VP Area":"VES"},{"DeptID":"345543","DeptDescr":"Academic Fails Centers","VP Area":"OK"}]}
NOW A WARNING:
This is what you DON'T want to do if you can fix the API you are getting this data from first. If any inconsistency appears, things will break. and in this example i'm not managing any edge case or exception, neither checking boundaries of arrays or wrapping things in try-catch blocks.

How to extract specific info from json

I am trying to get the subdivisions.names.en from the json below but keep getting a "TypeError: location.subdivisions.names is undefined" error. I'm sure it something simple & prob just need more sleep ;)
I can get other the info I need - this works:
alert(location.city.names.en + ' ' + location.postal.code);
But this does not:
alert(location.subdivisions.names.en);
Here is my json:
{
"continent": {
"code": "OC",
"geoname_id": xxx,
"names": {
"fr": "Océanie",
"pt-BR": "Oceania",
"zh-CN": "大洋洲",
"es": "Oceanía",
"de": "Ozeanien",
"ja": "オセアニア",
"en": "Oceania",
"ru": "Океания"
}
},
"location": {
"longitude": xxxx,
"latitude": -xxxx,
"time_zone": "Australia/Melbourne"
},
"subdivisions":
[
{
"names": {
"ru": "Виктория",
"pt-BR": "Vitória",
"en": "Victoria"
},
"iso_code": "VIC",
"geoname_id": xxxx
}
],
}
"subdivisions": [ ... indicates, that this variable is an array of objects. You need to index the proper entry:
alert(location.subdivisions[0].names.en);
Please be aware that there must not be any entry
"subdivisions": [], ...
and a lot of them, so there must be some logic / check on the index.
location.subdivisions.length might help
"subdivisions" is defined as an array in your json file. Depending on what is intended, either change it to be just a hash (remove the square brackets) or modify the access to
alert(location.subdivisions[0].names.en);
You should have a look at what is JSON and how to use it properly because apparently you seem to lack the basic knowledge of how JSON is structured.
That being said, the reason why location.subdivisions.names.en is undefined is because in your JSON it does not exist.
subdivisions is also an array of objects.
In order to access what you are trying to you must use subdivisions[0].names.en.

JSON - Accessing JSON Array and assigning variables

I have the following JSON in a file called census.json:
{
"areas": [
"UnitedStates", [{
"STATEORREGION": "United States",
"1910POPULATION": 92228531,
"1920POPULATION": 106021568,
"1930POPULATION": 123202660,
"1940POPULATION": 132165129,
"1950POPULATION": 151325798,
"1960POPULATION": 179323175,
"1970POPULATION": 203211926,
"1980POPULATION": 226545805,
"1990POPULATION": 248709873,
"2000POPULATION": 281421906,
"2010POPULATION": 308745538,
"1910CHANGE": 21,
"1920CHANGE": 15,
"1930CHANGE": 16.2,
"1940CHANGE": 7.3,
"1950CHANGE": 14.5,
"1960CHANGE": 18.5,
"1970CHANGE": 13.3,
"1980CHANGE": 11.5,
"1990CHANGE": 9.8,
"2000CHANGE": 13.2,
"2010CHANGE": 9.7
}],
"Alabama", [{
"STATEORREGION": "Alabama",
"1910POPULATION": 2138093,
"1920POPULATION": 2348174,
"1930POPULATION": 2646248,
"1940POPULATION": 2832961,
"1950POPULATION": 3061743,
"1960POPULATION": 3266740,
"1970POPULATION": 3444165,
"1980POPULATION": 3893888,
"1990POPULATION": 4040587,
"2000POPULATION": 4447100,
"2010POPULATION": 4779736,
"1910CHANGE": 16.9,
"1920CHANGE": 9.8,
"1930CHANGE": 12.7,
"1940CHANGE": 7.1,
"1950CHANGE": 8.1,
"1960CHANGE": 6.7,
"1970CHANGE": 5.4,
"1980CHANGE": 13.1,
"1990CHANGE": 3.8,
"2000CHANGE": 10.1,
"2010CHANGE": 7.5
}],
"Alaska", [{
"STATEORREGION": "Alaska",
"1910POPULATION": 64356,
"1920POPULATION": 55036,
"1930POPULATION": 59278,
"1940POPULATION": 72524,
"1950POPULATION": 128643,
"1960POPULATION": 226167,
"1970POPULATION": 300382,
"1980POPULATION": 401851,
"1990POPULATION": 550043,
"2000POPULATION": 626932,
"2010POPULATION": 710231,
"1910CHANGE": 1.2,
"1920CHANGE": -14.5,
"1930CHANGE": 7.7,
"1940CHANGE": 22.3,
"1950CHANGE": 77.4,
"1960CHANGE": 75.8,
"1970CHANGE": 32.8,
"1980CHANGE": 33.8,
"1990CHANGE": 36.9,
"2000CHANGE": 14,
"2010CHANGE": 13.3
}], ]
}
I am trying to access the different values stored in the array using the following:
$.getJSON("../data/census.json", function (json) {
var censusData = json;
console.log(censusData.areas);
});
This logs all the states to the console as an object, so I then tried to go down another level with:
$.getJSON("../data/census.json", function (json) {
var censusData = json;
console.log(censusData.areas.UnitedStates);
});
but this returns "undefined". How can I drill down another level? Ideally I would like to access each states population for a specific year and then assign it to a variable that I can use later.
the pattern here is after each string name we have an array of related information:
so you can convert it to an object like
var _result = {};
for ( var i=0;i<arr.length/2;i++){
_result[arr[i]] = arr[i+1];
}
then you can directly access those information by their string names
like this
censusData.areas.UnitedStates
will return an array after this transformation
There is currently no second level as there are commas instead of colons between the state names and their properties:
"Alaska", [{
"STATEORREGION":"Alaska",
"1910POPULATION":64356,
...
This makes the values "Alaska" and the dictionary of properties adjacent elements in a list. It seems what you want is:
"Alaska": [{
"STATEORREGION":"Alaska",
"1910POPULATION":64356,
...
your json data is invalid try this,
{"areas" : [
"UnitedStates", [{
"STATEORREGION":"United States",
"1910POPULATION":92228531,
"1920POPULATION":106021568,
"1930POPULATION":123202660,
"1940POPULATION":132165129,
"1950POPULATION":151325798,
"1960POPULATION":179323175,
"1970POPULATION":203211926,
"1980POPULATION":226545805,
"1990POPULATION":248709873,
"2000POPULATION":281421906,
"2010POPULATION":308745538,
"1910CHANGE":21,
"1920CHANGE":15,
"1930CHANGE":16.2,
"1940CHANGE":7.3,
"1950CHANGE":14.5,
"1960CHANGE":18.5,
"1970CHANGE":13.3,
"1980CHANGE":11.5,
"1990CHANGE":9.8,
"2000CHANGE":13.2,
"2010CHANGE":9.7
}],
"Alabama", [{
"STATEORREGION":"Alabama",
"1910POPULATION":2138093,
"1920POPULATION":2348174,
"1930POPULATION":2646248,
"1940POPULATION":2832961,
"1950POPULATION":3061743,
"1960POPULATION":3266740,
"1970POPULATION":3444165,
"1980POPULATION":3893888,
"1990POPULATION":4040587,
"2000POPULATION":4447100,
"2010POPULATION":4779736,
"1910CHANGE":16.9,
"1920CHANGE":9.8,
"1930CHANGE":12.7,
"1940CHANGE":7.1,
"1950CHANGE":8.1,
"1960CHANGE":6.7,
"1970CHANGE":5.4,
"1980CHANGE":13.1,
"1990CHANGE":3.8,
"2000CHANGE":10.1,
"2010CHANGE":7.5
}],
"Alaska", [{
"STATEORREGION":"Alaska",
"1910POPULATION":64356,
"1920POPULATION":55036,
"1930POPULATION":59278,
"1940POPULATION":72524,
"1950POPULATION":128643,
"1960POPULATION":226167,
"1970POPULATION":300382,
"1980POPULATION":401851,
"1990POPULATION":550043,
"2000POPULATION":626932,
"2010POPULATION":710231,
"1910CHANGE":1.2,
"1920CHANGE":-14.5,
"1930CHANGE":7.7,
"1940CHANGE":22.3,
"1950CHANGE":77.4,
"1960CHANGE":75.8,
"1970CHANGE":32.8,
"1980CHANGE":33.8,
"1990CHANGE":36.9,
"2000CHANGE":14,
"2010CHANGE":13.3
}]
]
}
So I was able to access the data by changing the structure of the JSON to the following:
{"areas" : [
[{
"STATEORREGION":"United States",
"POPULATION1910":92228531,
"1920POPULATION":106021568,
"1930POPULATION":123202660,
"1940POPULATION":132165129,
"1950POPULATION":151325798,
"1960POPULATION":179323175,
"1970POPULATION":203211926,
"1980POPULATION":226545805,
"1990POPULATION":248709873,
"2000POPULATION":281421906,
"2010POPULATION":308745538,
"1910CHANGE":21,
"1920CHANGE":15,
"1930CHANGE":16.2,
"1940CHANGE":7.3,
"1950CHANGE":14.5,
"1960CHANGE":18.5,
"1970CHANGE":13.3,
"1980CHANGE":11.5,
"1990CHANGE":9.8,
"2000CHANGE":13.2,
"2010CHANGE":9.7
}],
[{
"STATEORREGION":"Alabama",
"1910POPULATION":2138093,
"1920POPULATION":2348174,
"1930POPULATION":2646248,
"1940POPULATION":2832961,
"1950POPULATION":3061743,
"1960POPULATION":3266740,
"1970POPULATION":3444165,
"1980POPULATION":3893888,
"1990POPULATION":4040587,
"2000POPULATION":4447100,
"2010POPULATION":4779736,
"1910CHANGE":16.9,
"1920CHANGE":9.8,
"1930CHANGE":12.7,
"1940CHANGE":7.1,
"1950CHANGE":8.1,
"1960CHANGE":6.7,
"1970CHANGE":5.4,
"1980CHANGE":13.1,
"1990CHANGE":3.8,
"2000CHANGE":10.1,
"2010CHANGE":7.5
}],
[{
"STATEORREGION":"Alaska",
"1910POPULATION":64356,
"1920POPULATION":55036,
"1930POPULATION":59278,
"1940POPULATION":72524,
"1950POPULATION":128643,
"1960POPULATION":226167,
"1970POPULATION":300382,
"1980POPULATION":401851,
"1990POPULATION":550043,
"2000POPULATION":626932,
"2010POPULATION":710231,
"1910CHANGE":1.2,
"1920CHANGE":-14.5,
"1930CHANGE":7.7,
"1940CHANGE":22.3,
"1950CHANGE":77.4,
"1960CHANGE":75.8,
"1970CHANGE":32.8,
"1980CHANGE":33.8,
"1990CHANGE":36.9,
"2000CHANGE":14,
"2010CHANGE":13.3
}]
]
}
Then I used:
$.getJSON( "../data/census.json", function( json ) {
var censusData = json;
console.log(censusData.areas[0][0].POPULATION1910);
});
Also note that I had to change 1910POPULATION to POPULATION1910 in order to access it without getting an error. There may be a better way to do this than changing every key name for every state.
When I want to access the next state I just changed censusData[0][0] to censusData[1][0] and so on and so forth.
The string "United States" is the first element in a list.
The data for The United States is in censusData.areas[1]. The structure of the JSON looks a bit strange.

Select2 -> Dynamic input returns as a string (jQuery

The format for my select 2 is as such:
$("#selectPretty").select2({
tokenSeparators: [","],
tags:["1", "2", "3", "php", "tiger", "test", "big bang theory", "bikes", "gh", "sd", "cheese", "food", "name", "jack", "chickens", "yikes!", "testing", "this", "is", "a", "questionj", "new", "question", "s"]
});
Which shows as such:
BUT, when I try to assign data into the box dynamically through AJAX by using this code:
$.ajax({
type: "POST",
url: "grabTags.php",
data: "tags="+$("#selectPretty").val(),
success:
function(msg2) {
alert(msg2);
$("#selectPretty").select2({
tokenSeparators: [","],
tags:[msg2]
});
}
});
It will come out like so:
For some reason the whole string is one option and I can't make it explode the result into different options...
Does anyone know what I can do here?
Note that 'tags:[msg2]' is returned from my grabTags.php file and 'msg2' = "1", "2", "3, etc...
Kindest Regards
Have you tried splitting the string that comes back from the PHP?
You can invoke the split method on a string (such as that which is returned from your PHP) and pass it a separator (in your case a ,).
Something like this should work:
$.ajax({
type: "POST",
url: "grabTags.php",
data: "tags="+$("#selectPretty").val(),
success:
function(msg2) {
//at this point, msg2 is the string: '"1","2","3"'
var myTags = msg2.split(',');
//myTags is now the array: ["1","2","3"]
$("#selectPretty").select2({
//tags needs to be an array, so pass in myTags
tags: myTags
});
}
});
The Select2 tags need a javascript array, not just a string surrounded by brackets.
So server side, have PHP spit out a json encoded array:
$tags = array("1", "2", "3", "php", "tiger", "test", "big bang theory", "bikes", "gh", "sd", "cheese", "food", "name", "jack", "chickens", "yikes!", "testing", "this", "is", "a", "questionj", "new", "question", "s");
echo json_encode($tags);
Now client side take that response in your ajax success handler, and assign it directly to tags.
Note that you may need to set dataType to json in your ajax call so that jQuery automatically parses the response as json. Not sure if it will figure that out on its own or not.
You may also be able to get rid of tokenSeparators if you provide an actual array as your tags.

extract part of json into another object and keep link between both

{
   "data": [
      {
         "date": "2013-03-07",
         "id": "2",
         "vt_color": "#548dd4",
         "vt_name": "follow up",
         "duration": "20",
         "time_booked": "12:00:00",
         "stats": "booked",
         "doctor_id": "00002",
         "patient_id": "00003"
      },
      {
         "date": "2013-03-08",
         "id": "3",
         "vt_color": "#76923c",
         "vt_name": "ultrasound",
         "duration": "30",
         "time_booked": "08:00:00",
         "stats": "booked",
         "pt_name": "demo patien",
         "dr_name": "Momen Alzalabany",
         "doctor_id": "00002",
         "patient_id": "00009"
      }
   ] 
}
what i want is to create another array out of this including vt_name,vt_color and index of data
so i use jquery
var words = [];
$.each(arr['data'],function(ref){
words[this.doctor_id].push({name: this.vt_color,color: this.vt_name,index:ref});
});
console.log(koko);
FAIL : words[this.do_id] is not defined....
how can i do this ? i want outcome to be
sorry i'm a newbie with json/js
i want outcome in php would be
['00002'=>[
['name'=>'follow up','color'=>'#548dd4',index=>[0,3,4]],
['name'=>'ultrasound','color'=>'#769dd4',index=>[1,5,8]]
]
]
Change the type of words to object (not array), since you want a map with a string (e.g. '00002') as key:
var words = {};
You want do add to an array which does not exist. You need to create it first:
words[this.doctor_id] = words[this.doctor_id] || []; // creates an array if not already existing
words[this.doctor_id].push({name: this.vt_color,color: this.vt_name,index:ref});

Categories

Resources