JSON Array Value Returns "[{" - javascript

I am writing a JSP web app and have converted a List of Java objects to a JSON array, and set it as an attribute. Right now I am trying to use JQuery to parse the Array and make separate JSON objects, but I have hit a big snag and can't find anything online where someone else has dealt with it. My servlet creates a properly formatted JSON array but when I access the value of the Array like so:
orders[0].value;
I get returned only "[{" in my JavaScript console. When I access the object
orders[0];
which is a hidden input that holds the Array, I find that the value looks like this:
value="[{"
firstname" : "John", "lastname" : "Doe", .....
As you can see, it looks like there is a newline after the "[{" and it is only recognizing it as the value. In the JavaScript console, the rest of the Array is highlighted differently as well.
I am totally stumped on how to solve that issue. Any advice is greatly appreciated.
Here's the code from my servlet that sets the attribute:
Object orders = request.getSession().getAttribute("orders");
String json = new Gson().toJson(orders);
try {
ArrayList<String> jsonList = extractObjects(json);
HttpSession session = request.getSession();
session.setAttribute("jsonOrders", jsonList);
//all prints on one line
System.out.println(jsonList);
} catch (Exception e) {
System.out.println("problem parsing JSON");
}
}
enum ParserState {
READING_OBJECT, READING_ARRAY
};
//create a JSON array
private ArrayList<String> extractObjects(String array) throws ParseException {
ParserState state = ParserState.READING_ARRAY;
StringBuilder currentObject = null;
ArrayList<String> result = new ArrayList<String>();
int i = 0;
int parenthesisBalance = 0;
for (char c : array.toCharArray()) {
switch (c) {
case '{': {
if (state == ParserState.READING_ARRAY) {
state = ParserState.READING_OBJECT;
currentObject = new StringBuilder();
}
parenthesisBalance++;
currentObject.append(c);
break;
}
case '}': {
if (state == ParserState.READING_ARRAY) {
throw new ParseException("unexpected '}' ", i);
} else {
currentObject.append(c);
parenthesisBalance--;
if (parenthesisBalance == 0) {
state = ParserState.READING_ARRAY;
result.add(currentObject.toString());
}
}
break;
}
default: {
if (state == ParserState.READING_OBJECT) {
currentObject.append(c);
}
}
}
i++;
}
return result;
}
Here's the input where I store the attribute:
<input type="hidden" value="${ sessionScope.jsonOrders }" id="orderData" />
when accessed with javascript using $('#orderData'), I get ,
<input type="hidden" value="[{"
firstname":"mike","lastname":"slagle","phonenumber":"17248802249","email":"[pslagle12#gmail.com]","duedate":"2016-11-24","product":"cake","comments":"this="" is="" 11242016="" 11.15","id":16,"price":11.15},="" {"firstname":"mike","lastname":"slagle","phonenumber":"17248802249","email":"[pslagle12#gmail.com]","duedate":"2016-11-24","product":"cake","comments":"this="" 11.15","id":17,"price":11.15},="" {"firstname":"patrick","lastname":"slagle","phonenumber":"7248802249","email":"[pslagle12#gmail.com]","duedate":"2016-11-24","product":"cookies","comments":"this="" cookies="" for="" patrick.","id":18,"price":15.66},="" {"firstname":"betsy","lastname":"horton","phonenumber":"7245443344","email":"[bhorton#hotmail.com]","duedate":"2016-12-17","product":"cupcakes="" ","comments":"this="" cupcakes="" bets.","id":19,"price":65.98},="" {"firstname":"morgan","lastname":"freeman","phonenumber":"864667234","email":"[freeman#hotmail.com]","duedate":"2016-02-15","product":"cake","comments":"this="" a="" cake="" morgan.","id":20,"price":200.75},="" {"firstname":"james","lastname":"boice","phonenumber":"7249983532","email":"[jboice#deadoldguy.net]","duedate":"2016-04-16","product":"cake="" and="" cookies","comments":"this="" an="" 18th="" century="" theologian","id":21,"price":54.95},="" theologian","id":22,"price":54.95}]"="" id="orderData">
And the way I am accessing the value which returns "[{":
var orders = $('#orderData')
console.log(orders[0].value);
EDIT
If I do this with my JSP:
<c:forEach var="i" items="${ jsonOrders }">
${ i }
</c:forEach>
The contents of the entire JSON array are printed on my page, which is what I want. It seems that I'm dealing with some weird interplay between JQuery and JSON arrays. Any suggestions would be greatly appreciated. I'm stumped. The only thing that gives me a value from the array is orders[0].value, which gives me "[{".

where orders comes in this?? According to my view, i have seen json value is assigned to variable value.
json value is assigned like a String i.e value="[{...}]" , pls remove the qoutes and assign like this value=[{....}]
then access field values like value[0]["firstname"] or value[0].firstname
you will get the value John.

var orders = JSON.parse($('#orderData'));
console.log(orders[0].value);

value="[{"
that right there tells you that value is not a JavaScript array of objects, but a String representation. You need to parse that String to get it into an actual JavaScript array that you can query.

You could use StringEscapeUtils.escapeJson if you don't mind importing another library
https://commons.apache.org/proper/commons-lang/apidocs/org/apache/commons/lang3/StringEscapeUtils.html
session.setAttribute("jsonOrders", StringEscapeUtils.escapeJson(jsonList));
Then in the javascript do this:
var orders = JSON.parse($('#orderData').val());

I chose to throw out this approach to getting my JSON altogether and instead am calling a servlet with a get request like so:
$.get('OrdersToJSONServlet', function(responseText) {
...
});
It is working.

Related

JQuery - How to loop through JSON using each

I have cached the JSON returned from an Ajax call and need to loop through this to display it. I get the error, 'Cannot read property 'title' of undefined'. Can anyone help?
$.each(cache['cat-'+cat], function(i, jd) {
var title= jd.title; //issue is here
)}
When I console.log(cache['cat-'+cat]) I get the below:
Object {
date: "2016-07-28T15:08:03.596Z",
data: '[{"id":471,"title":"Lines and Calls","solution_areas":"lines-calls"}]'
}
When I console.log(jd) within the loop I get the below:
2016-07-28T15:13:14.553Z
if I use console.log(jd.data); I get
undefined
I have tried the below but they don't work either:
var title= jd.data.title;
var title= jd.data[0].title;
Can anyone tell me what I am doing wrong?
The way you are currently using it, each is going to iterate over every property of the cache['cat-'+cat] object, of which there are two, date and data.
So your anonymous function function(i, jd)will be called twice. The first time, jdwill be the value of the date property (a string), the second time it will be the value of the data property (also a string, that happens to be formatted as JSON).
The contents of data need to be parsed before they can be accessed as an object/array, and given that data is formatted as an array, I am guessing that you actually want to iterate over that. Given the example provided, I would change it to:
$.each(JSON.parse(cache['cat-'+cat].data), function(i, jd) {
var title= jd.title;
});
You aren't accessing it properly. And since cache['cat-'+cat] is already the needed object, what's the purpose of $.each? Should be
var title= JSON.parse(cache['cat-'+cat].data)[0].title;
(because the title is in the data, and the data is JSON).
Demo:
var obj = {
date: "2016-07-28T15:08:03.596Z",
data: '[{"id":471,"title":"Lines and Calls","solution_areas":"lines-calls"}]'
};
var title= JSON.parse(obj.data)[0].title;
console.log(title);
Just need to understand what is JSON and what is STRING
cache['cat-'+cat].data return a string that need to convert to JSON before pass to each loop:
var dataCacheReturned = cache['cat-'+cat];
var objCache = dataCacheReturned.data; //Its return a string
objCache = JSON.parse(objCache); //Parse string to json
$.each(objCache, function(i, jd) {
var title = jd.title;
console.log(title);
});

Razor inside javascript key value declaration?

Given the need to extract data from a viewdata into a javascript key/value object:
var stuff = {
something : [#someVar.Prop2, #someVar.Prop3, etc]
};
I want to make the key have the "name" of someVar.Prop1 so that:
var stuff = {
#someVar.Prop1 : [#someVar.Prop2, #someVar.Prop3, etc]
};
Yet when I use the form in the second code block above, I get a Expected identifier, string or number error at the colon:
#someVar.Prop1 : [#someVar.Prop2, etc]
---------------X (x marks the spot)
How do I need to format the razor code so that it knows what I'm trying to say?
You should definitely not be trying to build your JSON piece by piece in your Razor view. That can go wrong very easily.
To expand on #DLeh's answer, what you can do is build a dictionary of the values you want, serialize that into JSON right in your Razor view, and assign that to your variable as shown here:
#{
// Assume that someVar is provided from somewhere else;
// this is just for demonstration
var someVar = new { Prop1 = "My Prop", Prop2 = "Prop Value", Prop3 = 7 };
}
#{
var obj = new Dictionary<string, object>
{
{someVar.Prop1, new object[] { someVar.Prop2, someVar.Prop3 } }
};
}
<script>
var stuff = #Html.Raw(Json.Encode(obj));
</script>
Rendered output:
<script>
var stuff = {"My Prop":["Prop Value",7]};
</script>
You can surround razor expressions in quotes ' or " to have them output into a javascript block. If you need the type to be preserved properly, you can use methods like parseInt() or parseFloat() to do so.
Example:
var stuff = {
value1 : '#val1',
value2 : [ parseInt('#val2'), parseInt('#val3') ]
};
If you need to left side of the assignment to be variable, you will probably need to build a json string and then parse that into the object. Something like this, my quotes might be off.
var stuffJson = '{"#value1" : "#val1", "#value2" : "[ #val2, #val3 ]" }';
var stuff = JSON.parse(stuffJson);
If you're doing this a lot, you might want to consider using the Json() method in your controller to help you build these more easily. You could build a dictionary of key / value and have that output json:
public virtual ActionResult GetStuff()
{
string value1 = "key1",
value2 = "key2",
val1 = "str1",
val2 = "str2",
val3 = "str3";
var dict = new Dictionary<string, object>
{
{ value1, val1},
{ value2, new List<string> { val2, val3} },
};
return Json(dict, JsonRequestBehavior.AllowGet);
}
Output:
{"key1":"str1","key2":["str2","str3"]}
The answer is to ignore Visual Studio's complaint of the problem as the code runs and throws no error:
#country.CountryCode: ['#someVar.Prop1', '#someVar.Prop2', etc],

How to get a sum of values in array in Google Native Client inside C++?

In my HTML
Let's say I have 2 input fields with values 3 and 4:
<form onchange="reload()">
<h2>Input:</h2>
<input type="number" id="val1" name="val1" value="3">
<input type="number" id="val2" name="val2" value="4">
<br><br>
<h2>Output</h2>
<input type="text" id="out" name="out" value="untouched by C++"><br>
</form>
In my JavaScript
I get the two values and push them into an array like so:
Module = document.getElementById('module');
var msg = [];
msg.push(Number(document.getElementById('val1').value));
msg.push(Number(document.getElementById('val2').value));
Then I send it to my C++ file to process the message
Module.postMessage(msg);
In my C++ file [ Here is where I am stuck. ]
The code I have to handle the message is below
virtual void HandleMessage(const pp::Var& var_message) {
std::string message = var_message.AsString();
pp::Var var_reply = pp::Var(message);
PostMessage(var_reply);
}
The issue is that it handles a string [actually it crashes if I my msg is of type of an array].
What I want it to expect and accept is an array or an object.
Basically, something like this:
virtual void HandleMessage(const pp::Var& var_message) {
pp::Var var_reply = var_message[0] + var_messgae[1]; // I expect this to be 3+4=7
PostMessage(var_reply);
}
Can somebody help me figure out how to expect an array or an object from JavaScript inside my C++ so that I could calculate values together and send the result back to JavaScript?
I have resolved the issue I had. The best approach is to use an object and pass the values as a JSON object, so
in JavaScript
values = {
"val1": Number(document.getElementById('val1').value),
"val2": Number(document.getElementById('val2').value)
};
msg = JSON.stringify(values);
Module.postMessage(msg);
Then handle the message and send the response back to JavaScript
in C++:
In the header you need to add picoJSON to handle JSON and sstream to work with isstringstream:
#include <sstream>
#include "picojson.h"
using namespace std;
then later in the code:
virtual void HandleMessage(const pp::Var& var_message) {
picojson::value v;
// pass the message that was sent from JavaScript as a string
// var_message.AsString() will be in form "{\"val1\":4,\"val2\":4}");
// and convert it to istringstream
istringstream iss2((string)var_message.AsString());
// parse iss2 and extract the values val1 and val2
string err = picojson::parse(v, iss2);
int val1 = (int)v.get("val1").get<double>();
int val2 = (int)v.get("val2").get<double>();
// finally send the message and you'll see the sum in the JavaScript
PostMessage( val1 + val2 );
}
The documentation hasn't been updated yet, but as of pepper_29 there is now a pp::VarArray interface for accessing arrays.
You can see the header file for the new C++ interface here.
Here's how you can use it (untested):
virtual void HandleMessage(const pp::Var& var_message) {
if (!var_message.is_array()) return;
pp::VarArray array(var_message);
// Do some stuff with the array...
uint32_t length = array.GetLength();
double sum = 0;
for (uint32_t i = 0; i < length; ++i) {
pp::Var element = array.Get(i);
if (element.is_number()) {
sum += element.AsDouble();
}
}
pp::Var var_reply(sum);
PostMessage(var_reply);
}
I have the same problem, i want to send a string array
var nativeArray = new Array();
nativeArray[0] = "Item 1"
nativeArray[1] = "Item 2"
naclModuleElement.postMessage(nativeArray)
and nothing gets called in the HandleMessage
Sending nativeArray.length works and shows '2' in NaCl side
After some investigation, i saw that there is no AsArray() function in pp::Var class
Only primitives are available
There is a class pp:VarArrayBuffer which could be used to send/recieve binary info.. this could help (did not download the example posted in it though)

How to encode cookie with javascript/jquery?

I am working on an online shop together with my friend. He set a cookie for me with PHP with the amount of added products to the Cart. The cookie is called "cart", and the variable with the amount of the products is called "items".
And I have to read the cookie and get the value of "cart" back with javascript and print it in the HTML document, but I have no Idea how to use it, can you please help me? I have never worked with cookies or JSON before, but I think it should be done with JSON, can you please explain it to me how it works?
when I do : console.log(document.cookie);
I receive something like this: cart=%7B%22items%22%3A%7B%228%22%3A1%7D%7D;
And I have no idea how to encode it.
Thank you
That is the URL encoded equivalent of {"items":{"8":1}} which is the JSON string you want.
All you have to do is decode it and parse the JSON:
var cart = JSON.parse(decodeURIComponent(document.cookie.cart));
Then logging cart should give you an object with an 'items' property that you can access as needed.
EDIT:
As an example, here's a way to iterate through the items and determine the total number of items and the total of all their quantities.
var items_total = 0,
quantity_total = 0;
for (var prop in cart.items) {
items_total += 1;
quantity_total += cart.items[prop];
}
console.log("Total Items: " + items_total);
console.log("Total Quantities: " + quantity_total);
Looks like you just need to decode it, then you will want to parse/eval it to get a workable object:
var obj, decoded = decodeURIComponent(document.cookie.cart);
if(window.JSON && JSON.parse){
obj = JSON.parse(decoded);
} else {
eval('obj = ' + decoded);
}
// obj == {"items":{"8":1}};

Dynamic Associative Array Creation in Javascript from JSON

It sounds a lot more complicated than it really is.
So in Perl, you can do something like this:
foreach my $var (#vars) {
$hash_table{$var->{'id'}} = $var->{'data'};
}
I have a JSON object and I want to do the same thing, but with a javascript associative array in jQuery.
I've tried the following:
hash_table = new Array();
$.each(data.results), function(name, result) {
hash_table[result.(name).extra_info.a] = result.(name).some_dataset;
});
Where data is a JSON object gotten from a $.getJSON call. It looks more or less like this (my JSON syntax may be a little off, sorry):
{
results:{
datasets_a:{
dataset_one:{
data:{
//stuff
}
extra_info:{
//stuff
}
}
dataset_two:{
...
}
...
}
datasets_b:{
...
}
}
}
But every time I do this, firebug throws the following error:
"XML filter is applied to non-xml data"
I think you can use the JSON response as an associative array. So you should be able to go directly in and use the JSON.
Assuming you received the above example:
$('result').innerHTML = data['results']['dataset_a']['dataset_two']['data'];
// Or the shorter form:
$('result').innerHTML = data.results.dataset_a.dataset_two.data;
Understand that I haven't tested this, but it's safer to use the square brackets with a variable than it is to use parenthesis plus the name with the dot accessor.
Your example is failing because of some convoluted logic I just caught.
$.each(data.results), function(name, result) {
hash_table[result.(name).extra_info.a] = result.(name).some_dataset;
});
Now, the foreach loop goes through the variable data.results to find the internal elements at a depth of 1. The item it finds is given to the lambda with the key of the item. AKA, the first result will be name = "datasets_a" item = object. Following me so far? Now you access the returned hash, the object in item, as though it has the child key in name ... "datasets_a". But wait, this is the object!
If all else fails... write your result JSON into a text field dynamically and ensure it is formatted properly.
Why would you want to change an array into another array ?-)
-- why not simply access the data, if you want to simplify or filter, you can traverse the arrays of the object directly !-)
This works. Just dump it into a script block to test.
d = {
'results':{
'datasets_a':{
'dataset_one':{
'data':{
'sample':'hello'
},
'extra_info':{
//stuff
}
},
'dataset_two':{
///
}
///
},
'datasets_b':{
///
}
}
}
alert(d.results.datasets_a.dataset_one.data.sample)
I hope this pasted in correctly. This editor doesn't like my line breaks in code.
d = {
'results':{
'datasets_a':{
'dataset_one':{
'data':{
'sample':'hello'
},
'extra_info':{
//stuff
}
},
'dataset_two':{
///
}
///
},
'datasets_b':{
///
}
}
};
alert(d.results.datasets_a.dataset_one.data.sample)

Categories

Resources