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],
Related
Website that I'm making is in two different languages each data is saved in mongodb with prefix _nl or _en
With a url I need to be able to set up language like that:
http://localhost/en/This-Is-English-Head/This-Is-English-Sub
My code look like that:
var headPage = req.params.headPage;
var subPage = req.params.subPage;
var slug = 'name';
var slugSub = 'subPages.slug_en';
var myObject = {};
myObject[slugSub] = subPage;
myObject[slug] = headPage;
console.log(myObject);
Site.find(myObject,
function (err, pages) {
var Pages = {};
pages.forEach(function (page) {
Pages[page._id] = page;
});
console.log(Pages);
});
After console.log it I get following:
{ 'subPages.slug_en': 'This-Is-English-Sub',
name: 'This-Is-English-Head' }
Is you can see objectname subPages.slug_en is seen as a String insteed of object name..
I know that javascript does not support underscores(I guess?) but I'm still looking for a fix, otherwise i'll be forced to change all underscores in my db to different character...
Edit:
The final result of console.log need to be:
{ subPages.slug_en: 'This-Is-English-Sub',
name: 'This-Is-English-Head' }
Insteed of :
{ 'subPages.slug_en': 'This-Is-English-Sub',
name: 'This-Is-English-Head' }
Otherwise it does not work
The reason you are seeing 'subPages.slug_en' (with string quotes) is because of the . in the object key, not the underscore.
Underscores are definitely supported in object keys without quoting.
Using subPages.slug_en (without string quotes) would require you to have an object as follows:
{ subPages: {slug_en: 'This-Is-English-Sub'},
name: 'This-Is-English-Head' }
Which you could set with the following:
myObject['subPages']['slug_en'] = subPage;
Or simply:
myObject.subPages.slug_en = subPage;
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.
I'm using hashmap in Java to hold three pairs of servers in format (name,size), and then pass this hashmap to Javascript.
In Javascript there is no comma after the last entry:
data: [
{
name : "client3",
y:23,
},
{
name : "client1",
y:245,
},
{
name : "client2",
y:23,
}]
so I don't know how to get rid of this comma in Java using HashMap iterator :
for (Map.Entry<String, String> entry : listClientSize.entrySet()) {
String name = entry.getKey().toString();;
String size = entry.getValue();
out.println("name : \""+name+"\",");
out.println("y:"+size+",");
out.println("},");
}
Any ideas?
Instead of writing the comma at the end of the loop, write it at the beginning. It's much easier to check first iteration than last iteration.
boolean first = true;
for (Map.Entry<String, String> entry : listClientSize.entrySet()) {
String name = entry.getKey().toString();;
String size = entry.getValue();
if (first)
first = false;
else
out.println("},");
out.println("{");
out.println("name : \""+name+"\",");
out.println("y:"+size);
}
out.println("}");
BTW: You were missing the print of the start-brace {, and had a comma after the y value.
Update: Since that pattern for handling first iteration is so common, and the action is so simple (usually just appending a separator), I usually collapse the code as follows (don't do this if you have strict coding standards):
if (first) first = false; else out.println("},");
It seems you are creating JSON, so consider using proper JSON parser to generate your results. For instance with gson library your code could look like
Class containing single informations you want to store
public class Server{
private String name;
private int value;
public Server(String name, int value) {
this.name = name;
this.value = value;
}
//getters and setters
}
You can use this class like:
List<Server> list = new ArrayList<>();
list.add(new Server("1", 245));
list.add(new Server("2", 23));
list.add(new Server("3", 23));
Gson gson = new GsonBuilder().setPrettyPrinting().create();
String json = gson.toJson(list);
System.out.println(json);
which will generate:
[
{
"name": "1",
"value": 245
},
{
"name": "2",
"value": 23
},
{
"name": "3",
"value": 23
}
]
You can add later data = at start if you absolutely need it.
If you can use Java 8, use StringJoiner
final StringJoiner stringJoiner = new StringJoiner(",");
Map<String,String> listClientSize = new HashMap<String,String>(){{
put("client3","23");
put("client1","245");
put("client2","23");
}};
for (Map.Entry<String, String> entry : listClientSize.entrySet()) {
String name = entry.getKey().toString();;
String size = entry.getValue();
stringJoiner.add(String.format("{name:\"%s\", y:%s}", name, size));
}
System.out.println(stringJoiner.toString());
To get rid of the comma after the y property, which is the last property in the object, just do this:
for (Map.Entry<String, String> entry : listClientSize.entrySet()) {
String name = entry.getKey().toString();;
String size = entry.getValue();
out.println("name : \""+name+"\",");
out.println("y:"+size);
out.println("},");
}
To get rid of the comma at the very end, instead of printing from the for loop, build up a string and then use substring to cut off the last character after your for loop, then print the string
One easy thing you could try is accumulating the string to print in a StringBuilder, and then stripping the last comma, using substring. It should look like this:
StringBuilder output = new StringBuilder();
for (Map.Entry<String, String> entry : listClientSize.entrySet()) {
String name = entry.getKey();
String size = entry.getValue();
output.append("{name :\"").append(name).append("\", ");
output.append("y: ").append(size).append("},");
}
String toPrint = output.substring(1, output.size() - 1);
out.println(toPrint);
You probably need a way to tell if its not last entry then append the comma. One simplistic way is to keep a counter n n increment each iteration. If counter != hashmap size append comma
I want to encode a Javascript object into a JSON string and I am having considerable difficulties.
The Object looks something like this
new_tweets[k]['tweet_id'] = 98745521;
new_tweets[k]['user_id'] = 54875;
new_tweets[k]['data']['in_reply_to_screen_name'] = "other_user";
new_tweets[k]['data']['text'] = "tweet text";
I want to get this into a JSON string to put it into an ajax request.
{'k':{'tweet_id':98745521,'user_id':54875, 'data':{...}}}
you get the picture. No matter what I do, it just doesn't work. All the JSON encoders like json2 and such produce
[]
Well, that does not help me. Basically I would like to have something like the php encodejson function.
Unless the variable k is defined, that's probably what's causing your trouble. Something like this will do what you want:
var new_tweets = { };
new_tweets.k = { };
new_tweets.k.tweet_id = 98745521;
new_tweets.k.user_id = 54875;
new_tweets.k.data = { };
new_tweets.k.data.in_reply_to_screen_name = 'other_user';
new_tweets.k.data.text = 'tweet text';
// Will create the JSON string you're looking for.
var json = JSON.stringify(new_tweets);
You can also do it all at once:
var new_tweets = {
k: {
tweet_id: 98745521,
user_id: 54875,
data: {
in_reply_to_screen_name: 'other_user',
text: 'tweet_text'
}
}
}
You can use JSON.stringify like:
JSON.stringify(new_tweets);
I can pass a variable from MVC ASP.NET by using this :
var lastCategoryId = '<%=Model.CS.LastSelectedCategory %>';
This work fine with string or integer but how do I do with an array of strings? I have tried to pass the array the same way but the variable is set to System.String[] ?
You could let .NET handle all the heavy lifting for you with this simple line of code.
This assumes you're using MVC Razor syntax.
var yourJavaScriptArray = #Html.Raw(Json.Encode(Model.YourDotNetArray));
For newer versions of MVC, use:
var yourJavaScriptArray = #Html.Raw(Json.Serialize(Model.YourDotNetArray));
You could JSON serialize it. This way could could pass even more complex values and not worry about escaping simple quotes, double quotes, etc :
var categoriesList = <%= new JavaScriptSerializer().Serialize(new[] { "value1", "value2" }) %>;
Writing an HTML helper to do this would be even better:
public static class HtmlExtensions
{
public static string JsonSerialize(this HtmlHelper htmlHelper, object value)
{
return new JavaScriptSerializer().Serialize(value);
}
}
and then in your view:
<script type="text/javascript">
var categoriesList = <%= Html.JsonSerialize(new[] { "value1", "value2" }) %>;
</script>
This should do
var someArray=[<%foreach (var s in myStringArray){%>'<%=s%>',<%}%>];
something like this:
<script type="text/javascript">
var myArr = [<%=string.Join(",", strArr.Select(o => "\"" + o + "\"")) %>];
</script>
One liner:
var data = [#Html.Raw(String.Join(",", Model.MyArray.Select(i => "'" + i + "'")))];
So easy, so simple
<script type="text/javascript">
var array = #Html.Raw(
Json.Encode(
(Model).Select(m=> new
{
id= m.ID,
name=m.Name
})
)
);
</script>
Output is:
[{"id":1,"name":"Name of 1"}, {"id":2,"name":"Name of 2"}, ...];
Using Json.NET
var yourlist = JSON.parse('#Html.Raw(JsonConvert.SerializeObject(Model.YourList))');
You need to format the array into a JavaScript array syntax.
var someArray = [<%= Model.SomeArray.Select(x => "'" + x +"'")
.Aggregate((x,y) => x + ", " + y); %>];
This will surround each entry by single quotes and then join them together with commas between square brackets.
Updated: removed extra parenthesis.
Just wanted to provide an answer using Razor syntax:
We have a Dictionary<int, int> that we are rendering for a jQuery Sparkline, in the form of "an array of arrays".
var usageData = [ #string.Join(",", Model.UsageData.Select(d => string.Format("[{0},{1}]", d.Key, d.Value)).ToArray()) ];
Which is used like so:
$('#sparkline').UsageSparkline(usageData, { tooltipFormatter: cachedTooltips });
This is what we get when viewing the source:
var usageData = [ [-13,0],[-12,1],[-11,0],[-10,0],[-9,1],[-8,1],[-7,0],[-6,2],[-5,2],[-4,0],[-3,0],[-2,9],[-1,3],[0,4] ];
$('#sparkline').UsageSparkline(usageData, { tooltipFormatter: cachedTooltips });