Accessing JSON values with a variable - javascript

I'm trying to access JSON data with jQuery and grab a specific set of values based on a variable. I've done this before using [] but for some reason I can't figure out what is going wrong this time.
My JSON file (being read in by getJSON, and named jsonmaker.php) looks like this:
{"0107001":{"label":"Canada","x":"0","y":"0.34"},"0107002":{"label":"USA","x":"-0.16","y":"0.53"}}
I then have a function which is essentially this:
function addAttrib(attrib) {
$.getJSON("jsonmaker.php", function(data) {
alert(data[attrib].label);
}
}
But it keeps returning undefined. Any idea what I'm doing wrong? I've checked to make sure the var going to attrib is 0107001, no problems there.
Also, I know my JSON file is a php file so I could filter what's returned to match the attrib value, but I'm looking to develop something that can run purely on HTML and JS, so I could just pack the JSON file for the project and take it with me. No need for a web server w/ PHP etc.

The data access itself works for me:
var data = {"0107001":{"label":"Canada","x":"0","y":"0.34"},"0107002":{"label":"USA","x":"-0.16","y":"0.53"}};
var attrib = "0107002";
alert(data[attrib].label); // USA
Make sure that attrib remains untouched between the moment you call addAttrib() and the moment when the AJAX request completes and your anonymous callback function gets called.
Update: is this your real code? You have at least one syntax error:
function addAttrib(attrib) {
$.getJSON("jsonmaker.php", function(data) {
alert(data[attrib].label);
}); // <- Please note missing ");"
}

In my experience, $.getJSON() doesn't always return an object. Depending on the MIME type that the server returns along with the JSON, you might end up with a string instead of an object. Check what data contains. If it's a string, you must manually parse it using eval() (old style) or JSON.parse() (new browsers only).

try to list all properties from data, to have sure the data is being returned:
for (var p in data){
if (data.hasOwnProperty(p){
alert(data[p]);
}
}
It's not your solution but with this you can know how your data is coming.

Related

How do I get a JS script to parse raw JSON from a file?

I have a really simple JSON data file with no kind of wrapping, e.g.:
[{"name:","fakename"}, {"lang:", "javascript"}]
I'm trying to use this data in a js script in the same directory. I'm reading in both files in the document <head>, like such:
<script id="myJSON" src="data.json"></script>
<script src="myScript.js"></script>
and then the part I'm stuck on is how to get myScript to SEE that JSON data. In the script I can do:
d = document.getElementById("myJSON");
console.log(d);
The script returns the DOM element "myJSON" but I don't know how to access its JSON contents. I figured it would be a property like 'text' or 'value' or 'innerHTML' but I don't see it anywhere. I've tried various combinations of the type attribute in the tag but none of that makes any difference.
I know I could use an API like fetch but that's more complexity than I want. My best idea so far is to edit the json file to put an identifier at the beginning of the json file, like var myJSON = '[{"json"}]'; so then myScript would have a clear handle to JSON.parse(myJSON). But that's an extra step in an automated process which I don't want (or think I need).
How do I get my JS to see this "anonymous" JSON?
If you don't want to use fetch, you could use the server side code (PHP, ASP, etc) to write the text of the JSON into a hidden div in the page, and then you could use getElementByID to get the text, followed by parse to get an object that represents the JSON data.
This was not that much extra code but it was kind of a pain to wrap my head around. I had to wrap everything in a .then clause of fetch, or of an async function which called fetch. Here's what my code ended up looking like.
readJSONFile().then(jq => {
for (i = 0; i < jq.length; ++i) {
console.log( jq[i].myJSONKey )
});
async function readJSONFile() {
const response = await fetch('data.json');
const jq = await response.json();
return jq;
}

Sharing Data Between Javascript Files

I have a script that generates a JSON formatted string. I want to use the data contained in this string in another script. I'm not sure where to even start. I've thought about running both scripts from the same directory and somehow outputting the JSON data into a text file and then loading it into the second script but this seems like more of a workaround than an actual solution. Is it possible to somehow call the second script from the first and pass it the data? Much like passing data between functions in a single script?
FWIW I have tried simply combining the functions the two scripts perform into one, but this has caused me countless headaches with no progress. For simplicity sake I'd prefer to keep the functions performed by each script separate (apart from the obvious data sharing requirement!).
Any advice or a point in the right direction would be greatly appreciated.
If JSON data is less than 5 mb then you can use localStorage to save the output in browser.
In first js file:
function fOne(){
var jsonStr = ''; //insert some json data here
localStorage.setItem("myJson", JSON.stringify(jsonStr)); //save data
}
In your second js file:
function fTwo(){
if (localStorage.getItem("myJson") !== null) {
var passedJson = localStorage.getItem("myJson"); //get saved data anytime
}
}
It is hard to say without some code to reference but maybe just a global variable with a check if its null.
var myJsonString = null;
function one () {
var jsonString = "[]";
myJsonString = jsonString;
}
function two () {
//string not set so bail
if (myJsonString === null) { return; }
}
So it actually depends what environment you are programming in. If its a web browser, all of the code is in the global space actually and is run in order. so if you have <script src="file1"> then <script src="file2"> in your html file, and you put x = 10 in the first file and use it in the second, you will have no problems. If you are using node.js, I can post a solution for that as well, just let me know.
(btw if you put x = 10 in the second file and reference it from the first it will throw an error)
There are ways of avoiding this, such as using a document.ready function or wrapping things in functions and then calling them at the end. You need to make sure that functions and variables are created before being used (this is a common mistake beginners make and are confused by)

The file is emptied when I use file_put_contents

Main issue was solved in comments, although one of the bonus questions is still open and the other's solution could use some improvement
All of this takes place on a webhosting service, the folder structure is as follows:
The JavaScript and PHP files are in /public_html/, the JSON is in /public_html/data/.
In my JS code, I'm sending a POST request with some data for my JSON file:
console.log(objdata.buildings[0].coords);
var params = JSON.stringify(objdata);
if (objdata.buildings[0].coords != " "){
$.ajax({
type: "POST",
data: params,
url: "writecoords.php",
success: function(data){
console.log(params);
console.log(data);
console.log("AJAX success");
},
error: function(){
console.log("failed to send POST");
alert("error");
}
});
}
PHP file:
<?php
function debug_to_console($data){
if(is_array($data) || is_object($data))
{
echo("\n".json_encode($data));
} else {
echo("\n".$data);
}
}
$newJSON = json_decode(file_get_contents('php://input'));
debug_to_console($newJSON);
if (is_writable('data/strogi.json')) {
$a = file_put_contents('data/strogi.json', $newJSON);
if(! $a)
debug_to_console("Wrote nothing");
debug_to_console("PHP write success");
} else {
debug_to_console("PHP write failed");
}
?>
As you can see, I perform a check at every possible point to see if I'm actually processing non-empty data -- I log the value of the key in question, the AJAX request is sent only if it was changed, I log the data being sent and I log the data my PHP file receives and decodes.
I also check if the file is writable to avoid a possible permission problem, and only then I try to write to the file. The file comes out empty and I get the following outputs in console
params is my JSON object as a single line;
data is: my JSON object as a single line with line breaks before every new object and all cyrillic converted to \u format, "Wrote nothing!", "PHP write success";
"AJAX success"
If I check the strogi.json file after this, it's absolutely empty.
To rule out a problem with the format of passed JSON object, I tried writing to a simple test.txt file in the same directory as the .php, which turns out empty as well.
I tried using the method described here, but nothing changed.
I tried using a FTP upload (the method is pointed out somewhere in the comments here), and I got "No such file or directory" returned both for the strogi.json and test.txt files. I used both public_html/test.txt and test.txt as file name.
I tried using the combination of locks FILE_APPEND | LOCK_EX, and no changes happen to either of the files.
My questions are:
Why?
Can a different solution be used if all of this is taking place in the .done() callback for $.getJSON() called on the same file?
Follow-up question worthy of a separate section:
coords is a 3-dimensional array
[
[[x1,y1],[x2,y2],...]]
]
where the external array contains up to two arrays. The first array contains points of the external polygon and (if present) second array contains points of the internal polygon that serves as a cutout.
The code in question is an attempt to make submitting the coords array to strogi.json work for at least one object.
What I'm trying to do, in general, is
$.getJSON() the data/strogi.json file
go through the buildings[] array of objects inside it in the .done()
callback
for each object, check if "coords" is " " (default value)
If it is, a constructor is called to build a polygon using a map API, and when construction is finished, $.ajax is used to submit coords extracted through one of API's functions.
As of now, I'm submitting the whole JSON object, because I'm only working with one of the inner objects, but I imagine resubmitting the whole thing is excessive with multiple objects presented.
Is there a way to pass objdata.buildings[i].coords with the index i to PHP to change the "coords" key value in JSON for a certain buildings[i] object?
Do I need to make any changes to the way I'm processing data to make my JSON valid upon further reads? I assume I'd have to change the "coords" value from [[[x1,y1],[x2,y2]]] (the way it's passed now) to something like this (pastebin because there's no code formatting even though I'm using the 4 space indent)
for it to work, right? How do I do that? partly solved by going through the array in JS with two for() loops and applying toString() to every coordinate, there's gotta be a better way

JSON Reader issue: cannot access jsonData

I have a strange thing going on here: I am using a JSON reader within a store to fetch search results. After loading the store I receive data or error states (built together as a JSON, too). So in both ways I get a successfully response, so I have to check the JSON for myself to trap "error conditions". But I cannot access the jsonData property that shhould be a JSON object within the reader. Chrome tells me that:
I can access the applyDefaults though (it returns true in that case) but not the jsonData.
My code looks like this:
var result = searchStore.getProxy().getReader();
console.log(result.jsonData);
The output is "undefined". As you can see in the picture the jsonData object holds my JSON (with the isError property I wanted to access).
What I am doing wrong?
You need to think more async and think of the timing it takes for a request to return and when you are trying to get the jsonData. Instead of using console.log, set a breakpoint or use the debugger; statement so you can freeze the browser and walk through the code. You can then inspect variables and such to see what the object looks like.
Try to access your JSON data in a success callback, to make sure the data is gathered from the server.

JMeter modifying output to file from XML Stream

I'm attempting to write a JMeter script which after receiving and XML response from a server, extracts a string from it on the fly (drops the first part of the response) and writes it to a file.
Currently I use a Save Response Data to write to ChannelData_UAT_1 (filename). All good, it writes happily.
Then I add a BSF PreProcessor BEFORE it, and use javascript to try and extract the string. It's a bunch of XML tags, I want everything from "<Markets>" onwards.
I use:
function extract_markets(str)
{
marketIndex = str.indexOf("<Markets");
__log(marketIndex);
length = str.length;
marketString = str.substring(markeIndex, length-1);
return str;
}
vars.put('ChannelData_UAT_1', extract_markets(vars.get('ChannelData_UAT_1')));
As far as I can tell, ChannelData_UAT_1 is the variable the data is in. However this is only mentioned in the Save Response Data. But I can't do it afterwards otherwise it'll have already written to the file.
The current performance is for it to receive the response and write to the file. No filtering is done - as if my javascript didn't exist.
Anything small or obvious that I've missed? Suggestions?
I believe the issue stems from the fact that ChannelData_UAT_1 is not a variable and how Save Response Data works.
ChannelData_UAT_1 is the file name, not the content of the file.
You need to modify the contents of the "Response". You can replace the value of the page response with the value of your function.
I think the code would look something like this:
import org.apache.jmeter.util.JMeterUtils;
import org.apache.jmeter.samplers.SampleResult;
prev.setResponseData(extract_markets(vars.get('ChannelData_UAT_1')));
Source:
http://www.javadocexamples.com/java_examples/org/apache/jmeter/samplers/SampleResult/

Categories

Resources