Why is this JSON file reading strangly - javascript

I have a JSON document here. I have validated it with JSlint.
The JSON is of this format:
[{
"date": "2017-02-10",
" action": "Do a thing",
"state": "closed",
"url": "https:someurl.com"
},
....
I have some HTML here, which exists only to read and output the JSON.
The HTML looks like this:
<html>
<head>
<script type="text/javascript" src="http://code.jquery.com/jquery-1.7.2.min.js"></script>
</head>
<body>
<script>
deadlines = []
start();
function start() {
var req = new XMLHttpRequest();
req.open("GET", "http://joereddington.com/deadlines.json");
req.overrideMimeType("application/json");
req.send(null);
req.onreadystatechange = function() {
if (req.readyState == 4 && req.status == 200) {
var obj = JSON.parse(req.responseText);
deadlines = obj
for (deadline in deadlines) {
var output = '';
for (var property in deadline) {
console.log(property)
output += property + ': ' + deadline[property] + '; ';
}
console.log(output);
console.log(deadline.date)
console.log(deadline.action)
}
}
};
}
</script>
</body>
However, when I try and list the properties of each object, I get very strange results:
rather than the names and values I'm looking for. Can someone tell me what I'm doing wrong?

$.each(JSON.parse(deadlines), function (index, deadline) {
var output = '';
for (var property in deadline) {
console.log(property)
output += property + ': ' + deadline[property] + '; ';
}
console.log(output);
console.log(deadline.date);
console.log(deadline.action);
});
Your JSON string contains extra space. It should be "action" not " action".

for...in loops over the keys (since it's an array: "0", "1" ...). Use for...of or forEach or a basic for loop.
I recommend forEach like this:
deadlines.forEach(function(deadline) {
// ...
});

Related

Optimize trie implementation to search autocomplete

I have a project in which let the user to lookup for countries in a json file,
i've changed the structure of my json file from:
{
"AE": {"name": "United arab emirates","alternate": "UAE"},
"GB": {"name": "United kingdom","alternate": "Great Britain England","weight": "2.5"},
"US": {"name": "United states","alternate": "USA United States of America","weight": "3.5"},
.........
}
to this structure:
var countries = {
"name": "United arab emirates","alternate": "UAE",
"name": "United kingdom","alternate": "Great Britain England","weight": "2.5",
"name": "United states","alternate": "USA United States of America","weight": "3.5",
.........
}
but i couldn't figure how to edit the js code right to work with the json new structure,
here is the my code:
countries.js :
(function () {
'use strict';
// var log = console.log.bind(console);
// No timing in IE (sucker)
if(!console.time) {
console.time = console.timeEnd = function() {};
}
var countries, index;
function indexData() {
index = new T.Index({
'name' :'countries',
'indexSubstring': false,
'intersectResults': true
});
console.time('loading');
index.load(function(err) {
if(err) {
console.time('indexing');
Object.keys(countries).forEach(function(id) {
var country = countries[id];
var toIndex = [country.name , country.alternate].join(' ');
index.add(id, toIndex, country.weight || 1);
});
console.timeEnd('indexing');
console.time('saving');
index.save(function() {
console.timeEnd('saving');
});
}
else {
// Already loaded
window.index = index;
console.timeEnd('loading');
}
});
}
var request = new XMLHttpRequest();
request.onreadystatechange = function() {
if(request.readyState === 4) {
// Break the cyclic reference
request.onreadystatechange = null;
if (typeof request.responseText === "string") {
try {
countries = JSON.parse(request.responseText);
} catch(e) {
// do something
}
// Index, if data was loaded
if(countries) {
indexData();
}
}
}
};
request.open('get', 'data/countries.json', true);
request.send();
var search = document.getElementById('search');
var results = document.getElementById('results');
var lastVal;
function lookup() {
var query = search.value;
if(lastVal === query) {
return;
}
// Time the lookup
console.time('lookup: ' + query);
var ids = index.search(query);
console.timeEnd('lookup: ' + query);
// render the list
results.innerHTML = ids.map(function(id) {
var country = countries[id];
return '<li rel="' + id + '">' + country.name + '</li>';
}).join('');
lastVal = query;
}
search.addEventListener('keyup', lookup, false);
}).call(null);
countries.html:
<html>
<head>
<title>Trie.js</title>
<link rel="stylesheet" type="text/css" href="style.css">
<!--- trie-structure implementation ---->
<script type="text/javascript" src="https://rawgit.com/wunderlist/trie.js/master/dist/trie.js"></script>
</head>
<body>
<label>Type in a country name</label>
<input id="search" autocomplete="off" autofocus="autofocus" />
<ul id="results" />
<script type="text/javascript" src="js/countries.js"></script>
</body>
</html>
Update:
am also trying to limit the result to 5 suggestions. but i am stuck too.
please help thanks.
I don't understand what do you want to change with your search? It uses triejs library to build a tree structure, based on your json file, and triejs's search method to find the results based on the input. It looks like it works.
To limit the output you could slightly change your map function like this, for example:
results.innerHTML = ids.map(function(id, i) {
var country = countries[id];
if (i < 5) {
return '<li rel="' + id + '">' + country.name + '</li>';
}
}).join('');

how to parse JSON Response(Data) in javascript.

i am little new to javascript..Can anyone help me out from here.My JSON Response is like below:And i want to parse it and show it in the Table.
And my javascript code is below:
function parseData() {
var xmlhttp = new XMLHttpRequest();
var url = "http://beta.json-generator.com/api/json/get/NJqfdNMx-";
xmlhttp.onreadystatechange=function() {
if (this.readyState == 4 && this.status == 200) {
myFunction(this.responseText);
}
}
xmlhttp.open("GET", url, true);
xmlhttp.send();
function myFunction(response) {
var arr = JSON.parse(response);
var i;
var out = "<table>";
for(i = 0; i < arr.length; i++) {
out += "<tr><td>" +
arr[i].text +
"</td><td>" +
arr[i].text +
"</td><td>" +
arr[i].text +
"</td></tr>";
}
out += "</table>";
document.getElementById("id01").innerHTML = out;
}
}
Your JSON response contains object it doesn't directly contain array so you can't loop on response directly.
Your JSON response contains object with property text which contains further properties.
var arr = JSON.parse(response);
var text = arr.text;
This is value of text
{itemCount: 31, sleepActivities: Array[26], runActivities: Array[1], freePlayActivities: Array[3], bikeActivities: Array[1]}
Now you can loop on sleepActivities or runActivities or freePlayActivities or bikeActivities. You can loop over any array you want to get data.
for(i = 0; i < text.sleepActivities.length; i++) {
//your code
}
Need your Json data or Please go through this site
W3School JSON Handling Methods
which helps you more
Your response contains object but you don't need use JSON.parse. Because the response is pure JSON. You need to follow the below steps
var arr = response.text
it will return below result
Object {itemCount: 31, sleepActivities: Array[26], runActivities: Array[1], freePlayActivities: Array[3], bikeActivities: Array[1]}
for eg if you want to take sleepActivities from the response. Follow the process
var sleepActivities = response.text.sleepActivities
$.each(sleepActivities ,function(i,val){
console.log(val.heartRateSummary.averageHeartRate);
})

Parsing json array to array javascript

I have an array with json data:
var jsonString=[
{
"url": "http://www.anurl.com",
"tags": {
"Event": 6,
"Event1": 2
}
}
]
Now i want to build the next structure:
var data= [ {"text":"Event", "weight" : "6", "link" :"www.anurl.com"} //etc ];
Now i looked into the var array = $.parseJSON(JSON.stringify(jsonString));
and on the result i try to build my data array with .push();
But how can i insert the Event: 6 part? i cannot do array.tags[0] as array.tags will give me both of them.
So how can i solve this problem?
You are using object literals in javascript, the example you provided:
var jsonString=[{
"url": "http://www.anurl.com",
"tags": {
"Event": 6,
"Event1": 2
}
}];
jsonString is an array, and the element tags is an object NOT an array so you can access it like this:
var event = jsonString[0].tags.Event;
You can read the attributes of the tags object like the example below :
function loadArray(urls){
xhrDoc= new XMLHttpRequest();
if (xhrDoc.overrideMimeType)
xhrDoc.overrideMimeType('text/plain; charset=x-user-defined');
xhrDoc.onreadystatechange =function()
{
if (this.readyState == 4)
{
if (this.status == 200)
{
var data= this.response; //Here is a string of the text data
printUrls(data);
}
}
};
xhrDoc.open('GET', urls , true);
xhrDoc.send();
}
function printUrls(response) {
var arr = JSON.parse(response);
var i;
var out = "";
for(i = 0; i < arr.length; i++) {
console.log(arr[i].url);
console.log(arr[i].tags['Event']); // Read Event
console.log(arr[i].tags['Event1']); //// Read Event1
out = "URL : "+ arr[i].url + " Event : "+ arr[i].tags['Event']+ " Event1 : " + arr[i].tags['Event1'] + "\n";
}
document.getElementById("id01").innerHTML = out;
}
<!DOCTYPE html>
<html>
<head>
<script type="text/javascript" src="parseJsonFile.js"></script>
</head>
<body onload="loadArray('parseJson.json')">
<div id="id01"></div>
</body>
</html>
i solved it with
this code
var array =$.parseJSON(JSON.stringify(jsonString));
for (var i = 0; i < array.length; i++) {
var keys =array[i].tags;
var tags = Object.keys(keys);
for(var j = 0 ; j<tags.length; j++){
var obj = {text : tags[j], weight : keys[tags[j]] , link : array[i].url};
Jarray.push(obj);
}
}
The data is provided by an API, so the tag Event : 6 might be the next time Tomorrlowland : 3 the name of event and the weight are given by the API. That's why i can't use jsonString[0].tags.Event because the name event will be different every time.
Thanks all for helping me !

How to convert HTML to JSON using PHP?

I can convert JSON to HTML using JsontoHtml library. Now,I need to convert present HTML to JSON as shown in this site. When looked into the code I found the following script:
<script>
$(function(){
//HTML to JSON
$('#btn-render-json').click(function() {
//Set html output
$('#html-output').html( $('#html-input').val() );
//Process to JSON and format it for consumption
$('#html-json').html( FormatJSON(toTransform($('#html-output').children())) );
});
});
//Convert obj or array to transform
function toTransform(obj) {
var json;
if( obj.length > 1 )
{
json = [];
for(var i = 0; i < obj.length; i++)
json[json.length++] = ObjToTransform(obj[i]);
} else
json = ObjToTransform(obj);
return(json);
}
//Convert obj to transform
function ObjToTransform(obj)
{
//Get the DOM element
var el = $(obj).get(0);
//Add the tag element
var json = {'tag':el.nodeName.toLowerCase()};
for (var attr, i=0, attrs=el.attributes, l=attrs.length; i<l; i++){
attr = attrs[i];
json[attr.nodeName] = attr.value;
}
var children = $(obj).children();
if( children.length > 0 ) json['children'] = [];
else json['html'] = $(obj).text();
//Add the children
for(var c = 0; c < children.length; c++)
json['children'][json['children'].length++] = toTransform(children[c]);
return(json);
}
//Format JSON (with indents)
function FormatJSON(oData, sIndent) {
if (arguments.length < 2) {
var sIndent = "";
}
var sIndentStyle = " ";
var sDataType = RealTypeOf(oData);
// open object
if (sDataType == "array") {
if (oData.length == 0) {
return "[]";
}
var sHTML = "[";
} else {
var iCount = 0;
$.each(oData, function() {
iCount++;
return;
});
if (iCount == 0) { // object is empty
return "{}";
}
var sHTML = "{";
}
// loop through items
var iCount = 0;
$.each(oData, function(sKey, vValue) {
if (iCount > 0) {
sHTML += ",";
}
if (sDataType == "array") {
sHTML += ("\n" + sIndent + sIndentStyle);
} else {
sHTML += ("\"" + sKey + "\"" + ":");
}
// display relevant data type
switch (RealTypeOf(vValue)) {
case "array":
case "object":
sHTML += FormatJSON(vValue, (sIndent + sIndentStyle));
break;
case "boolean":
case "number":
sHTML += vValue.toString();
break;
case "null":
sHTML += "null";
break;
case "string":
sHTML += ("\"" + vValue + "\"");
break;
default:
sHTML += ("TYPEOF: " + typeof(vValue));
}
// loop
iCount++;
});
// close object
if (sDataType == "array") {
sHTML += ("\n" + sIndent + "]");
} else {
sHTML += ("}");
}
// return
return sHTML;
}
//Get the type of the obj (can replace by jquery type)
function RealTypeOf(v) {
if (typeof(v) == "object") {
if (v === null) return "null";
if (v.constructor == (new Array).constructor) return "array";
if (v.constructor == (new Date).constructor) return "date";
if (v.constructor == (new RegExp).constructor) return "regex";
return "object";
}
return typeof(v);
}
</script>
Now, I am in need of using the following function in PHP. I can get the HTML data. All what I needed now is to convert the JavaScript function to PHP function. Is this possible? My major doubts are as follows:
The primary input for the Javascript function toTransform() is an object. Is it possible to convert HTML to object via PHP?
Are all the functions present in this particular JavaScript available in PHP?
Please suggest me the idea.
When I tried to convert script tag to json as per the answer given, I get errors. When I tried it in json2html site, it showed like this: .. How to achieve the same solution?
If you are able to obtain a DOMDocument object representing your HTML, then you just need to traverse it recursively and construct the data structure that you want.
Converting your HTML document into a DOMDocument should be as simple as this:
function html_to_obj($html) {
$dom = new DOMDocument();
$dom->loadHTML($html);
return element_to_obj($dom->documentElement);
}
Then, a simple traversal of $dom->documentElement which gives the kind of structure you described could look like this:
function element_to_obj($element) {
$obj = array( "tag" => $element->tagName );
foreach ($element->attributes as $attribute) {
$obj[$attribute->name] = $attribute->value;
}
foreach ($element->childNodes as $subElement) {
if ($subElement->nodeType == XML_TEXT_NODE) {
$obj["html"] = $subElement->wholeText;
}
else {
$obj["children"][] = element_to_obj($subElement);
}
}
return $obj;
}
Test case
$html = <<<EOF
<!DOCTYPE html>
<html lang="en">
<head>
<title> This is a test </title>
</head>
<body>
<h1> Is this working? </h1>
<ul>
<li> Yes </li>
<li> No </li>
</ul>
</body>
</html>
EOF;
header("Content-Type: text/plain");
echo json_encode(html_to_obj($html), JSON_PRETTY_PRINT);
Output
{
"tag": "html",
"lang": "en",
"children": [
{
"tag": "head",
"children": [
{
"tag": "title",
"html": " This is a test "
}
]
},
{
"tag": "body",
"html": " \n ",
"children": [
{
"tag": "h1",
"html": " Is this working? "
},
{
"tag": "ul",
"children": [
{
"tag": "li",
"html": " Yes "
},
{
"tag": "li",
"html": " No "
}
],
"html": "\n "
}
]
}
]
}
Answer to updated question
The solution proposed above does not work with the <script> element, because it is parsed not as a DOMText, but as a DOMCharacterData object. This is because the DOM extension in PHP is based on libxml2, which parses your HTML as HTML 4.0, and in HTML 4.0 the content of <script> is of type CDATA and not #PCDATA.
You have two solutions for this problem.
The simple but not very robust solution would be to add the LIBXML_NOCDATA flag to DOMDocument::loadHTML. (I am not actually 100% sure whether this works for the HTML parser.)
The more difficult but, in my opinion, better solution, is to add an additonal test when you are testing $subElement->nodeType before the recursion. The recursive function would become:
function element_to_obj($element) {
echo $element->tagName, "\n";
$obj = array( "tag" => $element->tagName );
foreach ($element->attributes as $attribute) {
$obj[$attribute->name] = $attribute->value;
}
foreach ($element->childNodes as $subElement) {
if ($subElement->nodeType == XML_TEXT_NODE) {
$obj["html"] = $subElement->wholeText;
}
elseif ($subElement->nodeType == XML_CDATA_SECTION_NODE) {
$obj["html"] = $subElement->data;
}
else {
$obj["children"][] = element_to_obj($subElement);
}
}
return $obj;
}
If you hit on another bug of this type, the first thing you should do is check the type of node $subElement is, because there exists many other possibilities my short example function did not deal with.
Additionally, you will notice that libxml2 has to fix mistakes in your HTML in order to be able to build a DOM for it. This is why an <html> and a <head> elements will appear even if you don't specify them. You can avoid this by using the LIBXML_HTML_NOIMPLIED flag.
Test case with script
$html = <<<EOF
<script type="text/javascript">
alert('hi');
</script>
EOF;
header("Content-Type: text/plain");
echo json_encode(html_to_obj($html), JSON_PRETTY_PRINT);
Output
{
"tag": "html",
"children": [
{
"tag": "head",
"children": [
{
"tag": "script",
"type": "text\/javascript",
"html": "\n alert('hi');\n "
}
]
}
]
}
I assume that your html string is stored in $html variable. So you should do:
$dom = new DOMDocument();
$dom->loadHTML($html);
foreach($dom->getElementsByTagName('*') as $el){
$result[] = ["type" => $el->tagName, "value" => $el->nodeValue];
}
$json = json_encode($result, JSON_UNESCAPED_UNICODE);
Note: This algorithm doesn't support parent-child tags and fetch all tags as parent elements and parses all of them in a sorted queue. Of course, you can implement this feature by studying the DOMDocument classes features.
I wrote this to convert HTML Form tags to a JSON object. You may be able to build off of this.
class HtmlToJson {
public $html;
public $filter;
function __construct($html, $filter) {
$this->dom = new DOMDocument();
$this->dom->loadHTML( $html );
$this->jsonObj = array('form_tag_attrs'=>array(), 'form_values'=>array());
$this->filter = $filter;
}
function recursivePair($element, $tagName) {
if ( isset( $element->attributes ) ) {
$nameAttr = $element->getAttribute('name');
if ($nameAttr) {
$this->jsonObj['form_values'][$nameAttr] = $element->getAttribute('value');
}
if ($element->nodeName === $tagName) {
foreach ( $element->attributes as $attribute ) {
$this->jsonObj['form_tag_attrs'][ $attribute->name ] = $attribute->value;
}
}
}
if ( isset( $element->childNodes ) ) {
foreach ( $element->childNodes as $subElement ) {
$this->recursivePair( $subElement, $tagName );
}
}
}
function json() {
$element = ($this->filter ? $this->dom->getElementsByTagName($this->filter)->item(0) : $this->dom->documentElement);
$this->recursivePair($element, $this->filter);
return $this->jsonObj;
}
}
$formJson = new HtmlToJson($curlResult, 'form');
echo json_encode($formJson->json());

How do I iterate over a JSON structure? [duplicate]

This question already has answers here:
Loop (for each) over an array in JavaScript
(40 answers)
Closed 5 years ago.
The community reviewed whether to reopen this question 1 year ago and left it closed:
Original close reason(s) were not resolved
I have the following JSON structure:
[{ "id":"10", "class": "child-of-9" }, { "id": "11", "classd": "child-of-10" }]
How do I iterate over it using JavaScript?
var arr = [ {"id":"10", "class": "child-of-9"}, {"id":"11", "class": "child-of-10"}];
for (var i = 0; i < arr.length; i++){
document.write("<br><br>array index: " + i);
var obj = arr[i];
for (var key in obj){
var value = obj[key];
document.write("<br> - " + key + ": " + value);
}
}
note: the for-in method is cool for simple objects. Not very smart to use with DOM object.
Taken from jQuery docs:
var arr = [ "one", "two", "three", "four", "five" ];
var obj = { one:1, two:2, three:3, four:4, five:5 };
jQuery.each(arr, function() {
$("#" + this).text("My id is " + this + ".");
return (this != "four"); // will stop running to skip "five"
});
jQuery.each(obj, function(i, val) {
$("#" + i).append(document.createTextNode(" - " + val));
});
Use for...of:
var mycars = [{name:'Susita'}, {name:'BMW'}];
for (var car of mycars)
{
document.write(car.name + "<br />");
}
Result:
Susita
BMW
Please let me know if it is not easy:
var jsonObject = {
name: 'Amit Kumar',
Age: '27'
};
for (var prop in jsonObject) {
alert("Key:" + prop);
alert("Value:" + jsonObject[prop]);
}
If this is your dataArray:
var dataArray = [{"id":28,"class":"Sweden"}, {"id":56,"class":"USA"}, {"id":89,"class":"England"}];
then:
$(jQuery.parseJSON(JSON.stringify(dataArray))).each(function() {
var ID = this.id;
var CLASS = this.class;
});
Copied and pasted from http://www.w3schools.com, there is no need for the JQuery overhead.
var person = {fname:"John", lname:"Doe", age:25};
var text = "";
var x;
for (x in person) {
text += person[x];
}
RESULT: John Doe 25
mootools example:
var ret = JSON.decode(jsonstr);
ret.each(function(item){
alert(item.id+'_'+item.classd);
});
You can use a mini library like objx - http://objx.googlecode.com/
You can write code like this:
var data = [ {"id":"10", "class": "child-of-9"},
{"id":"11", "class": "child-of-10"}];
// alert all IDs
objx(data).each(function(item) { alert(item.id) });
// get all IDs into a new array
var ids = objx(data).collect("id").obj();
// group by class
var grouped = objx(data).group(function(item){ return item.class; }).obj()
There are more 'plugins' available to let you handle data like this, see http://code.google.com/p/objx-plugins/wiki/PluginLibrary
With nested objects, it can be retrieve as by recursive function:
function inside(events)
{
for (i in events) {
if (typeof events[i] === 'object')
inside(events[i]);
else
alert(events[i]);
}
}
inside(events);
where as events is json object.
Marquis Wang's may well be the best answer when using jQuery.
Here is something quite similar in pure JavaScript, using JavaScript's forEach method. forEach takes a function as an argument. That function will then be called for each item in the array, with said item as the argument.
Short and easy:
var results = [ {"id":"10", "class": "child-of-9"}, {"id":"11", "classd": "child-of-10"} ];
results.forEach(function(item) {
console.log(item);
});
this is a pure commented JavaScript example.
<script language="JavaScript" type="text/javascript">
function iterate_json(){
// Create our XMLHttpRequest object
var hr = new XMLHttpRequest();
// Create some variables we need to send to our PHP file
hr.open("GET", "json-note.php", true);//this is your php file containing json
hr.setRequestHeader("Content-type", "application/json", true);
// Access the onreadystatechange event for the XMLHttpRequest object
hr.onreadystatechange = function() {
if(hr.readyState == 4 && hr.status == 200) {
var data = JSON.parse(hr.responseText);
var results = document.getElementById("myDiv");//myDiv is the div id
for (var obj in data){
results.innerHTML += data[obj].id+ "is"+data[obj].class + "<br/>";
}
}
}
hr.send(null);
}
</script>
<script language="JavaScript" type="text/javascript">iterate_json();</script>// call function here
var jsonString = `{
"schema": {
"title": "User Feedback",
"description": "so",
"type": "object",
"properties": {
"name": {
"type": "string"
}
}
},
"options": {
"form": {
"attributes": {},
"buttons": {
"submit": {
"title": "It",
"click": "function(){alert('hello');}"
}
}
}
}
}`;
var jsonData = JSON.parse(jsonString);
function Iterate(data)
{
jQuery.each(data, function (index, value) {
if (typeof value == 'object') {
alert("Object " + index);
Iterate(value);
}
else {
alert(index + " : " + value);
}
});
}
Iterate(jsonData);
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
Another solution to navigate through the JSON document is JSONiq (implemented in the Zorba engine), where you can write something like this:
let $doc := [
{"id":"10", "class": "child-of-9"},
{"id":"11", "class": "child-of-10"}
]
for $entry in members($doc) (: binds $entry to each object in turn :)
return $entry.class (: gets the value associated with "class" :)
You can run it on http://public.rumbledb.org:9090/public.html

Categories