Java hashmap : Not write comma after printing the last entry - javascript

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

Related

Node-Red String into payload name

My array payload is like: msg.payload[index].temp. I cut the array in single parts to publish the single parts of the array via MQTT.
So I got msg.payload.temp and msg.parts.index.
msg:{
payload:{
address: "e4:32:a3:3a:99:97";
temp: "32"
}
parts: {
type: "array";
index: "16";
count: "17";
}
}
Is it possible to put the number of the index into the name msg.payload.temp? So I got something like msg.payload.temp_6. I tried to combine strings together like:
var temp = "msg.payload.temp_" + msg.parts.index.toString();
temp = payload.temp;
return msg;
Do I need a conversation from string to json so Node-Red detect the property?
You can add a property to msg.payload.
let index = 6;
msg.payload["temp"+index] = 'Whatever';
This will be available as
console.log(msg.payload.temp6); // Whatever

Double ToString keeping "en-US" format

Sounds simples - And I know it is... but i'm having issues with it and don't know why exactly..
I have a web application globalized (multilanguages).
When I click to change the language, this is my action:
public ActionResult ChangeCulture(string lang)
{
Thread.CurrentThread.CurrentCulture = new CultureInfo(lang);
Thread.CurrentThread.CurrentUICulture = Thread.CurrentThread.CurrentCulture;
var languageCookie = new HttpCookie("_language") { Value = lang, Expires = DateTime.UtcNow.AddYears(1) };
Response.Cookies.Remove("_language");
Response.SetCookie(languageCookie);
return Redirect(Request.UrlReferrer.PathAndQuery);
}
And I have a page to display some char (I'm using chart.js) and I need to bind a List<double> to a javascript array.
So this list looks like:
var list = new List<double> {144, 0, 540.23};
And I need a simples array in javascript:
var arr = [144, 0, 540.23];
Here is how I'm doing (razor):
var arr = [#string.Join(",", Model.ListWithDoubles.Select(x => Convert.ToString(x, new CultureInfo("en-US"))))]
The problem is:
When I'm using english language its works pretty. The others langues gives me integer numbers instead...
var arr = [144, 0, 540.23]; //en-US
var arr = [144, 0, 54023]; //pt-BR
var arr = [144, 0, 54023]; //it
var arr = [144, 0, 54023]; //es
Questions
Why?
How to fix?
Because in some other non en-US cultures the , and . have the exact opposite meaning and usage. If you are not displaying this data, only for chart purposes, then use CultureInfo.InvariantCulture when converting the double to string representation for the HTML. You should only convert to a culture specific string at the point you want to actually visually display that data value to the user.
var arr = [#string.Join(",", Model.ListWithDoubles.Select(x => Convert.ToString(x, CultureInfo.InvariantCulture)))]
The default format specifier for double is G so it will create output with only a decimal separator. As you want the raw number (not formatted for display) then this (CultureInfo.InvariantCulture) is what you need to pass, not the culture formatted string representation as that is for display only.
To illustrate that the code I posted works regardless of the culture of the current thread here is that code. Drop this into a console application and replace the Main method and run it. You will see that this works. Your issue lies elsewhere, not with this code.
static void Main(string[] args)
{
var cultures = new[] {"en-US", "pt-BR", "it", "es"};
var list = new List<double> {144, 0, 540.23};
Console.WriteLine("Without specifying a culture");
foreach (var culture in cultures.Select(isoCulture => new CultureInfo(isoCulture)))
{
System.Threading.Thread.CurrentThread.CurrentCulture = culture;
System.Threading.Thread.CurrentThread.CurrentUICulture = culture;
Console.WriteLine("Culture: " + culture.Name);
Console.WriteLine("Not defined: " + string.Join(",", list.Select(x => Convert.ToString(x))));
Console.WriteLine("CultureInfo.InvariantCulture: " + string.Join(",", list.Select(x => Convert.ToString(x, CultureInfo.InvariantCulture))));
}
Console.ReadLine(); // stops so you can see the results
}

JavascriptSerializer.Deserialize & Encoding

I use Vietnamese in input content to an textbox like "ngày 1".
The first time I do Javascript.Serialize an object & put it in array, store in cookie:
class sampleCookie
{
public string tripDate;
}
=>I got right value string is "ngày 1".
Again, I add new record to this list with another string "ngày 2".
=> I got the first record value string is "ngà y 1"
I can't figure out the way to Encoding for it.
What I'm missing?
This's my code
var estCookie = Request.Cookies[inputModel.SampleCookieName];
if (estCookie != null)
{
var serializer = new JavaScriptSerializer();
var serializeModel = serializer.Deserialize<ListSampleCookie>(estCookie.Value);
// I Update string value in here
//Put insert item to list
serializeModel.Add(new SampleCookie
{
TripDate = inputModel.TripDate ,
Memo = inputModel.Memo,
OptionFee = inputModel.OptionFee
});
// Serialize data
var sampleData = serializer.Serialize(serializeModel);
//Update cookie value
estCookie.Value = sampleData;
Response.AppendCookie(estCookie);
}

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 generate json-arrays with multiple types with jersey/jackson

i am trying to generate data for google charts with jersey but i don't know how to create a json array like this:
[
['Label', 'Value'],
['Memory', 80],
['CPU', 55],
['Network', 68]
]
arrays with a single type (1st line) are working but i don't know how to create arrays with multiple types like ['Memory',80]. i tried jersey without and with jackson but every time i try to generate an arraylist with multiple data-types i get something like this:
[
{
"type" : "xs:string",
"$" : "Memory"
}, {
"type" : "xs:int",
"$" : "80"
}
]
try this :
var array = [
{
"type" : "xs:string",
"$" : "Memory"
}, {
"type" : "xs:int",
"$" : "80"
}
];
//the output array
var translated = [];
for(var i=0; i<array.length; i+=2){
translated.push([array[i]["$"],array[i+1]["$"]]);
}
EDIT: If you need a number instead of a string
for(var i=0; i<array.length; i+=2){
var value = array[i+1]["$"];
//parse to number
if (/^([0-9])*[.]?[0-9]*$/.test(value)){
value = value.parseFloat(value);
}
translated.push([array[i]["$"],value);
}
In our application we are using the JsonSerializer-feature. You design you object in java like you want and than let the serializer do the rest for you.
There you have the "full" control how to do it.
Have a look at our code and add another jgen.writeStartArray() -> jgen.writeEndArray();
public class FolderChildrenSerializer extends JsonSerializer<FolderChildren> {
#Override
public void serialize(FolderChildren folderchildren, JsonGenerator jgen,
SerializerProvider provider) throws IOException, JsonProcessingException {
jgen.writeStartArray();
for (Item i : folderchildren.getList()) {
jgen.writeObject(i);
}
jgen.writeEndArray();
}
}

Categories

Resources