var addnote = function (title, body) {
var notes = [];
var note = {
title: title,
body: body
}
need explanation on the two lines under try
try {
var noteString = fs.readFileSync("data.json");
notes = JSON.parse(noteString);
} catch (e) {
}
And explanation on how duplicateNotes works ..
var duplicateNotes = notes.filter(function(note){
return note.title === title
})
if (duplicateNotes.length === 0) {
notes.push(note);
fs.writeFileSync("data.json", JSON.stringify(notes));
}
}
JSON.parse converts a JSON object to String.
{
field1:field1Value,
field2:fieldValue
}
If this is in Json format you can access it's elements using JSONObjectName.fieldName
But,if it's converted to String it looses it's JSON properties. You can't access fields in same way. Output will act like String.
need explanation on the two lines under try
var noteString = fs.readFileSync("data.json");
There are two kinds of response back asynchronous and synchronous. Synchronous call is like you will not start playing until you get a pass and score a goal. But, Asynchronous call is like you start playing with your friend but, you run near him and, there is a promise you won't shoot until you get the ball.
readFileSync will read the file and the next line will wait until it gets the pass.JSON.parse() will convert file content to JSON object.
And explanation on how duplicateNotes works ..
var duplicateNotes = notes.filter(function(note){
return note.title === title
})
Whenever a match is found , that element in notes will be pushed to duplicate note. That's all.
Am now using websocket in HTML5 to build my web app.
Because my previous work was based on TCP and I used CRC16 algorithm to wrap the content that will transfer to server side;
Construct message with CRC16 code below:
public static byte[] ConstructMessageWithCRC(string message)
{
//Message with a |
var messageToConstruct = message + "|";
//calculate CRC value
var crcCode = CRC16.CalculateCrc16(messageToConstruct);
var crcCodeShort = ushort.Parse(crcCode);
//CRC high value
var crcHigh = byte.Parse((crcCodeShort / 256).ToString());
//CRC low value
var crcLow = byte.Parse((crcCodeShort % 256).ToString());
var messageBytes = Encoding.Default.GetBytes(messageToConstruct);
var messageLength = messageBytes.Length;
var messageBytesWithCRC = new byte[messageLength + 2];
Array.Copy(messageBytes, 0, messageBytesWithCRC, 0, messageLength);
//append crc value to the message
messageBytesWithCRC[messageLength] = crcHigh;
messageBytesWithCRC[messageLength + 1] = crcLow;
return messageBytesWithCRC;
}
After server side received the data, it will calculate the content via CRC16 algorithm also to ensure that the data is correct.
Check CRC code below:
public static bool CheckMessageCRC(byte[] message, out string messageReceived)
{
//message length that received
var messageLength = message.Length;
//message received without crc value
var messageReceivedStrBytes = new byte[messageLength - 2];
Array.Copy(message, 0, messageReceivedStrBytes, 0, messageLength - 2);
//crc value received
var messageReceivedCrcBytes = new byte[2];
Array.Copy(message, messageLength - 2, messageReceivedCrcBytes, 0, 2);
//get the received message with correct decoding
var messageCalculatedString = Encoding.Default.GetString(messageReceivedStrBytes);
messageReceived = messageCalculatedString;
//get the received crc value
var currentCRC = byte.Parse(messageReceivedCrcBytes[0].ToString()) * 256 + byte.Parse(messageReceivedCrcBytes[1].ToString());
//crc value recalculate
var result = ushort.Parse(CRC16.CalculateCrc16(messageCalculatedString));
//comparison
if (currentCRC == result)
return true;
return false;
}
From above code, you can see what I did.
But in some articles that using websocket: Working with Websockets, it will use below code to handle the message directly:
//When the server is sending data to this socket, this method is called
ws.onmessage = function (evt) {
//Received data is a string; We parse it to a JSON object using jQuery
//http://api.jquery.com/jQuery.parseJSON/
var jsonObject = $.parseJSON(evt.data);
//Do something with the JSON object
};
//Creates an object that will be sent to the server
var myObject = {
Property: "Value",
AnotherProperty: "AnotherValue"
};
//We need to stringify it through JSON before sending it to the server
ws.send(JSON.stringify(myJsonObject));
It will directly send the data out without any check mechanism with the data. So if the data is intercepted by others and we won't know the data has been changed. Also, because of poor network, the data will arrival out of order, then below code won't work correctly, maybe we wanted data as ABC, but we got BCA:
var jsonObject = $.parseJSON(evt.data);
So for evt.data, just wonder how should we check the data transfer complete, data order correct, data content correct and so on.
I have googled a lot and didn't see any info regarding this, just want use this question to declare the right way to transfer data via websocket, thx.
EDIT:
My friend send me this: https://www.rfc-editor.org/rfc/rfc6455, in section 5.2
I think the protocol seems do this work already. Need more of your discusses on it. thx
I am investigating different data format (string vs masgpack byte) to encode and decode json efficiently. The jsons which I will recieve wont have any schema, atleast to keep it generic, I am assuming the jsons dont follow any specific schema.
Here is a small JS I used to evaluate:
// skip-eslint
var msgpack = require('msgpack5')() // namespace our extensions
, encode = msgpack.encode
, decode = msgpack.decode;
var helloWorldObj = { 'hello': 'world' };
var json = [];
var MAX_DECODE_REPEAT = 10000;
var MAX_REPEAT = 100;
console.log('json,data,time');
//msgpack
for ( var i=0;i<MAX_REPEAT;i++) {
json = [];
// create i+1 length json array
for(var k=0;k<=i;k++){
json.push(helloWorldObj);
}
// encode the json array
var encodedJson = encode(json);
var start = new Date().getTime();
// start decoding =>msgpack
for(var count=0;count<MAX_DECODE_REPEAT;count++){
decode(encodedJson);
}
var end = new Date().getTime();
var time = end-start;
console.log(json.length +',' + encodedJson.length + ','+time);
}
// JSON.parse
for ( var i=0;i<MAX_REPEAT;i++) {
json = [];
// create i+1 length json array
for(var k=0;k<=i;k++){
json.push(helloWorldObj);
}
// stringify the json array
var jsonString = JSON.stringify(json);
var start = new Date().getTime();
// start decoding =>msgpack
for(var count=0;count<MAX_DECODE_REPEAT;count++){
JSON.parse(jsonString);
}
end = new Date().getTime();
time = end-start;
console.log(json.length +',' + jsonString.length*2 + ','+time);
}
The logic is simple: I am increasing the length of the array and trying to find out the time taken by the decoder to decode the array 10000 times.
To my surprise, msgpack is taking 10 times more than json.parse. To decode 100 length array msgpack takes 4694 ms whereas json.parse takes only 378 ms, even though msgpack compresses the array to 1303 bytes from 3602 bytes (assuming each character takes 2 bytes).
What I initially assumed is a smaller size to decode would mean smaller time to decode but its definitely not the case. Any idea why? Do you see any issue with the program to evaluate msgpack?
Thanks
You're observing this difference because JSON.parse uses optimized native implementation under the hood, whereas msgpack5 is a pure-JS library. In other languages (i.e., C, Java, etc) MsgPack will be slightly faster in most situations (for example, see this benchmark: https://github.com/eishay/jvm-serializers/wiki).
There are few corner cases when there'll be significant difference. For example, it's likely that msgpack will be faster when serializing numbers/booleans.
So, I've parsed a response like this:
var g_rgListingInfo = JSON.parse( response );
response looks like this
{"321242653847396921":{"listingid":"321242653847396921","price":28338,"fee":4249,"publisher_fee_app":730,"publisher_fee_percent":"0.10000000149011612","currencyid":"2003","steam_fee":1416,"publisher_fee":2833,"asset":{"currency":0,"appid":730,"contextid":"2","id":"3038615825","amount":"1","market_actions":[{"link":"steam://rungame/730/76561202255233023/+csgo_econ_action_preview%20M%listingid%A%assetid%D1030942533801731526","name":"Inspect in Game..."}]}},"321242653843485871":{"listingid":"321242653843485871","price":30175,"fee":4525,"publisher_fee_app":730,"publisher_fee_percent":"0.10000000149011612","currencyid":"2003","steam_fee":1508,"publisher_fee":3017,"asset":{"currency":0,"appid":730,"contextid":"2","id":"1730491611","amount":"1","market_actions":[{"link":"steam://rungame/730/76561202255233023/+csgo_econ_action_preview%20M%listingid%A%assetid%D1030942533801731526","name":"Inspect in Game..."}]}},"782860982384213986":{"listingid":"782860982384213986","price":31305,"fee":4695,"publisher_fee_app":730,"publisher_fee_percent":"0.10000000149011612","currencyid":"2003","steam_fee":1565,"publisher_fee":3130,"asset":{"currency":0,"appid":730,"contextid":"2","id":"2815962367","amount":"1","market_actions":[{"link":"steam://rungame/730/76561202255233023/+csgo_econ_action_preview%20M%listingid%A%assetid%D1030942533801731526","name":"Inspect in Game..."}]}},"783987515556891867":{"listingid":"783987515556891867","price":31305,"fee":4695,"publisher_fee_app":730,"publisher_fee_percent":"0.10000000149011612","currencyid":"2003","steam_fee":1565,"publisher_fee":3130,"asset":{"currency":0,"appid":730,"contextid":"2","id":"3708699202","amount":"1","market_actions":[{"link":"steam://rungame/730/76561202255233023/+csgo_econ_action_preview%20M%listingid%A%assetid%D1030942533801731526","name":"Inspect in Game..."}]}},"783987515558623437":{"listingid":"783987515558623437","price":30957,"fee":4642,"publisher_fee_app":730,"publisher_fee_percent":"0.10000000149011612","currencyid":"2003","steam_fee":1547,"publisher_fee":3095,"asset":{"currency":0,"appid":730,"contextid":"2","id":"4462433815","amount":"1","market_actions":[{"link":"steam://rungame/730/76561202255233023/+csgo_econ_action_preview%20M%listingid%A%assetid%D1030942533801731526","name":"Inspect in Game..."}]}},"718685320959305952":{"listingid":"718685320959305952","price":34000,"fee":5100,"publisher_fee_app":730,"publisher_fee_percent":"0.10000000149011612","currencyid":"2001","steam_fee":1700,"publisher_fee":3400,"asset":{"currency":0,"appid":730,"contextid":"2","id":"4450043953","amount":"1","market_actions":[{"link":"steam://rungame/730/76561202255233023/+csgo_econ_action_preview%20M%listingid%A%assetid%D1030942533801731526","name":"Inspect in Game..."}]}},"796369492002647568":{"listingid":"796369492002647568","price":34500,"fee":5175,"publisher_fee_app":730,"publisher_fee_percent":"0.10000000149011612","currencyid":"2001","steam_fee":1725,"publisher_fee":3450,"asset":{"currency":0,"appid":730,"contextid":"2","id":"4024113558","amount":"1","market_actions":[{"link":"steam://rungame/730/76561202255233023/+csgo_econ_action_preview%20M%listingid%A%assetid%D3082226233578562378","name":"Inspect in Game..."}]}},"718684619833530742":{"listingid":"718684619833530742","price":22958,"fee":3442,"publisher_fee_app":730,"publisher_fee_percent":"0.10000000149011612","currencyid":"2002","steam_fee":1147,"publisher_fee":2295,"asset":{"currency":0,"appid":730,"contextid":"2","id":"4331886445","amount":"1","market_actions":[{"link":"steam://rungame/730/76561202255233023/+csgo_econ_action_preview%20M%listingid%A%assetid%D1030942533801731526","name":"Inspect in Game..."}]}},"788487401257494747":{"listingid":"788487401257494747","price":34783,"fee":5217,"publisher_fee_app":730,"publisher_fee_percent":"0.10000000149011612","currencyid":"2001","steam_fee":1739,"publisher_fee":3478,"asset":{"currency":0,"appid":730,"contextid":"2","id":"2315637005","amount":"1","market_actions":[{"link":"steam://rungame/730/76561202255233023/+csgo_econ_action_preview%20M%listingid%A%assetid%D1030942533801731526","name":"Inspect in Game..."}]}},"321242020664839911":{"listingid":"321242020664839911","price":34783,"fee":5217,"publisher_fee_app":730,"publisher_fee_percent":"0.10000000149011612","currencyid":"2001","steam_fee":1739,"publisher_fee":3478,"asset":{"currency":0,"appid":730,"contextid":"2","id":"4283078084","amount":"1","market_actions":[{"link":"steam://rungame/730/76561202255233023/+csgo_econ_action_preview%20M%listingid%A%assetid%D6944696178921031564","name":"Inspect in Game..."}]}}}
I put it in here: http://json.parser.online.fr/ this is the
result
The problem I'm having is that I fail to loop through the items. g_rgListingInfo.length is NaN. I tried to use forEach but that failed too.
I want to loop through all these "321242653847396921", "321242653843485871"... wich are always changing and obtain their listingid, price, fee etc.
I am pretty new to node.js so I'm sorry if this is a stupid question.
You have an object, not an array. So, to iterate the results, you have to either convert your object into an array or just iterate it as object.
Converting into array
Depending on what you need, this could be more convenient:
var myData = Object.keys(g_rgListingInfo).map(Number).sort().map(function (c) {
return g_rgListingInfo[c];
});
// Then you can just use the `myData` array
myData.forEach(function (current, index) {
/* do something */
});
// ...or using for loop
for (var i = 0; i < myData.length; ++i) {
var current = myData[i];
/* do something */
}
Iterating the object
You have to get the keys of the object iterate them (optionally you maybe want to sort them first).
// ["3124...", ...]
var numbers = Object.keys(g_rgListingInfo);
// Optional sort
numbers = numbers.map(Number).sort();
// Iterate the object keys
numbers.forEach(function (currentKey) {
var currentObject = g_rgListingInfo[currentKey];
});
I have a problem that seems complicated that I don't know how to solve.
My single page application uses knockoutJS and I want to cache my view model every time one of my input values change on my view.
Where the problem lies is the complexity of my view model. To use local storage I need to stringify my object but it has recursive values. I have some logic to handle this and stringify my object. But when I try to parse the JSON string back to an object, I lose my functions.
function cacheForm(agency) {
//var serialized = stringifyOnce(agency);
//var serialized = amplify.store("Agency", agency);#
//var obj = new Object();
//obj.test = "test";
value = agency;
var cache = [];
parsed = JSON.stringify(value, function (key, value) {
if (typeof value === 'object' && value !== null) {
if (cache.indexOf(value) !== -1) {
// Circular reference found, discard key
return;
}
// Store value in our collection
cache.push(value);
}
return value;
});
//var jsonString = JSON.stringify(cache);
//cache = null; // Enable garbage collection
var parsedRecursive = "{" + '"data"' + ":" + parsed + "," + '"expires"' + ":" + null + "}"; // Build the string based on how amplify likes it
var obj = eval('(' + parsed + ')')
var obj = jQuery.parseJSON(parsedRecursive);
//// Put the object into storage
//localStorage.setItem('Agency', parsedRecursive);
myData = JSON.parse(parsedRecursive, function (key, value) {
var type;
if (value && typeof value === 'object') {
type = value.type;
if (typeof type === 'string' && typeof window[type] === 'function') {
return new (window[type])(value);
}
}
return value;
});
//// Retrieve the object from storage
// var retrievedObject = localStorage.getItem('Agency');
// var obj = jQuery.parseJSON(parsedRecursive);
//var agency2 = mapping.fromJS(obj);
//agency;
//amplify.store("Agency", agency);
//amplify.store("Obj", obj);
//var store = amplify.store(); // Look at all items by not providing a key
}
});
I tried using eval but this returned an object without my data. To help you understand this is what my view model looks like, which is the agency parameter of cachForm.
Also I tried using amplify but because of my view model structure I run into the same issue.
I have also attached some screenshots to show what happens with my viewmodel in the code.
It is not a good idea to cache the whole viewModel. A viewModel contains observables, computeds and functions or events handlers.
You have better to cache the view model data, only the raw data.
On serialization :
So just serialize the view data (use ko.mapping.toJSON):
var json = ko.mapping.toJSON(viewModel);
In order to rebuild a proper view model it is better to have a initialisation function.
This is your view model constructor e.i. a function that adds the event handlers, functions and computed.
var initializer = your_constructor;
You also need to determine a cache key e.g. the page path.
var cacheItem = {data : json, constructor : initializer};
cache[key] = cacheItem;
On deserialization :
Get the cache item :
var cacheItem = cache[key];
var viewModel = JSON.parse(cacheItem.data);
Now viewModel contains the raw data.
viewModel = ko.mapping.fromJS(viewModel);
The properties were converted into observables.
If there is a constructor call it.
if(cacheItem.constructor)
cacheItem.constructor.call(viewModel);
Then your view model is as you stored it.
I hope it helps.
This is the answer I have posted in another post. They are both related.
JSON.parse returns children objects with null value, children values not being parsed