Difference between json.js and json2.js - json

Can someone tell me what the difference is between the 2 JSON parsers?
https://github.com/douglascrockford/JSON-js/blob/master/json.js
https://github.com/douglascrockford/JSON-js/blob/master/json2.js
I have a JSON file from 2007-04-13 (It has methods such as parseJSON). I don't see these methods in any of the new versions.

From their code:
// Augment the basic prototypes if they have not already been augmented.
// These forms are obsolete. It is recommended that JSON.stringify and
// JSON.parse be used instead.
if (!Object.prototype.toJSONString) {
Object.prototype.toJSONString = function (filter) {
return JSON.stringify(this, filter);
};
Object.prototype.parseJSON = function (filter) {
return JSON.parse(this, filter);
};
}
I guess parseJSON is obsolete, therefore the new version (json2) doesn't even use it anymore. However if your code uses parseJSON a lot you could just add this piece of code somewhere to make it work again:
Object.prototype.parseJSON = function (filter) {
return JSON.parse(this, filter);
};

Quoting here:
"JSON2.js - Late last year Crockford quietly released a new version of his JSON API that replaced his existing API. The important difference was that it used a single base object."

I also noticed that json2 stringified arrays differently than json2007.
In json2007:
var array = [];
array[1] = "apple";
array[2] = "orange";
alert(array.toJSONString()); // Output: ["apple", "orange"].
In json2:
var array = [];
array[1] = "apple";
array[2] = "orange";
alert(JSON.stringify(array)); // Output: [null, "apple", "orange"].

Related

How to make Json.stringify ignore certain class memebers?

I'm using the latest Haxe and HaxeFlixel to make a simple game prototype.
I have the following class...
class GameData
{
public var playerHealth: Int;
public var playerScore: Int;
public var levelName: String;
public function new(playerHealth: Int = 0, playerScore: Int = 0, levelName: String = "")
{
this.playerHealth = playerHealth;
this.playerScore = playerScore;
this.levelName = levelName;
}
}
I convert it to JSON as follows...
Json.stringify(new GameData(64, 512, "Level 1"));
Is there's a way I can make it so the stringify ignores certain members?
haxe.Json has no mechanism to exclude fields, so I would recommend using a third-party library such as json2object that does. Here you can simply annotate fields that should be ignored with #:jignored:
#:jignored
public var levelName:String;
var data = new GameData(100, 10, "Level 1");
var json = new json2object.JsonWriter<GameData>().write(data);
trace(json); // {"playerHealth": 100,"playerScore": 10}
There are some possible workarounds that don't involve adding a library to your project, but they don't seem very nice:
Don't serialize the object directly, but a structure that only includes the desired fields:
var data = new GameData(100, 10, "Level 1");
var json = Json.stringify({
playerHealth: data.playerHealth,
playerScore: data.playerScore
});
trace(json); // {"playerHealth":100,"playerScore":10}
Remove the unwanted fields after serialization - this seems rather hacky as it involves a lot of unnecessary overhead due to an additional Json.parse() and Json.stringify() call:
var json = Json.stringify(new GameData(100, 10, "Level 1"));
var data:haxe.DynamicAccess<String> = Json.parse(json);
data.remove("levelName");
json = Json.stringify(data);
trace(json); // {"playerHealth":100,"playerScore":10}
Depending on your exact situation, it can be desirable to make a slightly modified version of standard library's JsonPrinter - for example, in GMEdit I allow JSON objects to have an hxOrder: Array<String> field, which, if provided, determines the field order for printing, and is initialized to a static array. You can make a similar scheme for field inclusion/exclusion.

Confused on how notes = JSON.parse(noteString);

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.

Google Realtime circular JSON error when indexReference stored in collaborative map only when contained in an object

Trying to store indexReferences per user, I've found that when I store one (or more) directly in a map, it works fine. However, when stored in an object (or a custom realtime object), the realtime API generates Circular JSON errors.
This works fine:
function doRegisterTypes() {
gapi.drive.realtime.custom.registerType(MyCustomType, "MyCustomType");
MyCustomType.prototype.startPoints = gapi.drive.realtime.custom.collaborativeField('startPoints');
MyCustomType.prototype.endPoints = gapi.drive.realtime.custom.collaborativeField('endPoints');
MyCustomType.prototype.elements = gapi.drive.realtime.custom.collaborativeField('elements');
gapi.drive.realtime.custom.setInitializer(MyCustomType, initializeMyCustomType);
}
function initializeMyCustomType() {
var model = gapi.drive.realtime.custom.getModel(this);
this.startPoints = model.createMap();
this.endPoints = model.createMap();
this.elements = model.createList();
}
function initializeModel(model) {
var o = model.create("MyCustomType");
o.elements.pushAll(["foo", "bar"]);
var startIndex = o.elements.registerReference(0, false);
var endIndex = o.elements.registerReference(0, false);
o.startPoints.set(UserId, startIndex);
o.endPoints.set(UserId, endIndex);
model.getRoot().set("MyCustomObject", o);
}
But this doesn't, failing with circular JSON errors when storing the range object in the map:
function doRegisterTypes() {
gapi.drive.realtime.custom.registerType(MyCustomType, "MyCustomType");
MyCustomType.prototype.ranges = gapi.drive.realtime.custom.collaborativeField('ranges');
MyCustomType.prototype.elements = gapi.drive.realtime.custom.collaborativeField('elements');
gapi.drive.realtime.custom.setInitializer(MyCustomType, initializeMyCustomType);
}
function initializeMyCustomType() {
var model = gapi.drive.realtime.custom.getModel(this);
this.ranges = model.createMap();
this.elements = model.createList();
}
function initializeModel(model) {
var o = model.create("MyCustomType");
o.elements.pushAll(["foo", "bar"]);
var startIndex = o.elements.registerReference(0, false);
var endIndex = o.elements.registerReference(0, false);
// FAILS:
o.ranges.set(UserId, {start:startIndex, end:endIndex});
model.getRoot().set("MyCustomObject", o);
}
I should stress the error appears for a single indexReference, and whether the object is a specific custom type or not, and also WHENEVER the value is set into the map: while initializing the model or later. It's as if the indexReferences cannot be stored at anything but a "top level", though that makes little sense.
Feature? Bug? User stoopidity?
You can't store CollaborativeObjects within arbitrary json within a CollaborativeObject. CollaborativeObjects (including IndexReferences) must be stored directly in other CollaborativeObjects.
(There are a few reasons for this, mostly having to do with how the collaboration works.. json objects are treated as arbitrary blobs whose contents are ignored.)
In this case, you could create a Range custom object type that has a start and end CollaborativeField. (Or a CollaborativeList with 2 elements..)

SAPUI5 get single property from JSON-Model

I am currently trying to figure out how I can retrieve a single value from a sap.ui.model.json.JSONModel
in my main view:
var gConfigModel = new sap.ui.model.json.JSONModel();
var getConfigCallback = function(config) {
gConfigModel.setData(config);
};
oController.getConfiguration(getConfigCallback);
console.log(gConfigModel);
in my controller:
getConfiguration : function(callback) {
var sServiceUrl = "/sap/opu/odata/sap/xxx/ConfigurationSet('Initialize')";
var config = {};
callback(config);
$.getJSON(sServiceUrl).done(function(data) {
config = data.d;
callback(config);
});
},
In my console.log statement I can see that the data was successfully passed from the backend and successfully set to the JSON model. My requirement is to store the value of attribute Editable in a single variable.
I already tried gConfigModel.getProperty('/'), didnt work. tried to access gConfigModel.oData was undefined .. How can I store it in a single value?
Solution Comment: If you catch data from a backend, you have to take care how long it takes. data can be available later then expected, in my case I added 1s timeout, afterwards I can access the property easily
setTimeout(function() {
console.log(gConfigModel.getProperty('/Editable'));
}, 1000);
I wouldn't advise using the model's getData() method since it is deprecated.
A much better solution is to use gConfigModel.getProperty("/Editable")
(I'm using the root slash here since your property resides in the root of your model)
In the same way, you can also set your data:
gConfigModel.setProperty("/Editable", <your new value>) instead
First of all, thanks for the effort to find solutions of our Problems! (at least, those regarding It stuff.. :) )
I've found a solution which I think is a little bit more save because the timeout is maybe somewhat arbitrary - it would depend on the machine or the amount of data that is to be fetched?
Therefore, I am using an attachRequestCompleted function:
with sUrl_2="path-to-my-service";
var oModel_2 = new sap.ui.model.json.JSONModel(sUrl_2);
oModel_2.attachRequestCompleted(function(data) {
//now, i can access the data stored in the oModel_2, either by getProperty, or by DOM: oModel_2.oData.d.Vendor
gv_selLieferant = oModel_2.getProperty("/d/Vendor");
gv_selEinkOrg = oModel_2.getProperty("/d/PurchOrg");
gv_selEinKGru = oModel_2.getProperty("/d/PurGroup");
});
<script src="https://openui5.hana.ondemand.com/resources/sap-ui-core.js" id="sap-ui-bootstrap" data-sap-ui-theme="sap_bluecrystal" data-sap-ui-libs="sap.m"></script>
<script>
function getConfiguration(callback) {
var sServiceUrl = "/sap/opu/odata/sap/xxx/ConfigurationSet('Initialize')";
var config = {};
var data = {
"d": {
"_metadata": "",
"Backup01": "01",
"Editable": "True"
}
};
setTimeout((function() {
config = data;
callback(config);
})(), 2000);
};
var gConfigModel = new sap.ui.model.json.JSONModel();
var getConfigCallback = function(config) {
gConfigModel.setData(config);
alert(gConfigModel.getProperty("/d/Editable"));
};
getConfiguration(getConfigCallback);
</script>

flash get function's argument name

I want to get all arguments names of a function inside the function
example:
function fct(var1:string,var2:string){
var names:Array=...
trace(names);
}
must trace : var1,var2
Thanks!
Simply put, this is not possible. The closest you can get is the argument number and value. See below:
function fct( ... args ):void {
for ( var v:Object in args ) {
trace( v + ": " + args[v] );
}
}
var str1:String = "this is a test";
var str2:String = "this is another test";
fct( str1, str2 );
//output
//0: this is a test
//1: this is another test
For future reference, you can use ... + a variable name to allow for as many arguments as you need. Regardless, you should just need to access args[ INDEX ] rather than the actual variable name, which you wouldn't be able to access anyway because there would be no way to apply scope (such as variableName[ "propertyName" ])
It is impossible like native method, but you can use metadata tag to set arguments names. I create simple example. But i don't understand how it can help you in real projects:
[Arguments(param1="arg1",param2="arg2")]
public function test(arg1:Number, arg2:Number):void {
var desc_xml:XML = describeType(Object(this).constructor);
var metas_xml:XMLList = desc_xml.factory.method.(#name == "test");
var args_xml:XMLList = metas_xml.metadata.(#name == "Arguments");
for each (var argx:XML in args_xml.arg)
{
trace(argx.#value.toXMLString());
}
};
I use flex 4.6. Don't forget add each existing Metadata tags to the compiler argument with “-keep-as3-metadata+=Arguments”. It need for compile release versions.