Convert Unity3D json to Javascript Object json format - javascript

My whole workflow:
Unity3D(encoding class data in json format) -> WebGL Build -> Javascript html -> Socket.IO
Those data type(int, byte[], string) should be readable in socket.io.
This is the function I used in Unity3D, in order to convert a class to json string.
JsonUtility.ToJson();
When I print in node.js, I got this and it couldn't understand the data type.
{"Type":0,"Str":"AAA","Byte":[0]}
If it's correct, I will get below result when I print in node.js.
{ Type: 0, Str: 'AAA', Byte: [ 0 ] }
Thus, I need a solution to convert them.
Could someone please tell me the easiest way to convert them in C#?
UPDATE: more info
Below C# script is working in Unity3D, and I want to convert this:
Application.ExternalEval(#"
if(typeof window.socketIO !== 'undefined')
{
window.socketIO.emit('" + e + #"', " + data + #");
}
");
https://docs.unity3d.com/Manual/webgl-interactingwithbrowserscripting.html
Because "Application.ExternalEval" is depreciated in latest Unity, I need to convert them into something like this:
mergeInto(LibraryManager.library, {
WebSocketEmitData: function (_e, _data) {
var e = Pointer_stringify(_e);
var data = Pointer_stringify(_data);
if(typeof window.socketIO !== 'undefined')
{
window.socketIO.emit(e, data);
}
}
});
Thanks!

I use Javascript/Unity/C# heavily on my current project, I strongly advice you to use JSON.NET For Unity it will emit a universal json format, that is similar to the one on the javascript JSON class.
Usage pretty similar to unity's primitive json utility.
JsonUtility.ToJson => JsonConvert.SerializeObject
JsonUtility.FromJson => JsonConvert.DeserializeObject<T>
That being said, let's convert a json string from the C# object to a javascript object.
// Convert your json string to a native javascript object.
var jsObject = JSON.parse(str);
console.log(jsObject.Type); // outputs 0
console.log(jsObject.Byte.length); // outputs 1
console.log(jsObject.Str); // outputs AAA
// Convert your native javascript object to another of certain type,
// will assume the desired javascript type is Player in a namespace Database
var player = Object.assign(new Database.Player(), jsObject);
Also instead of if(typeof window.socketIO !== 'undefined') use if(typeof window.socketIO) it is cleaner, checks for both null and undefined.

Finally I found the answers myself. I didn't notice that I can emit object instead of string message. and now it works!
WebSocketEmitData: function (_e, _data) {
var e = Pointer_stringify(_e);
var data = Pointer_stringify(_data);
var obj = JSON.parse(data);
if(typeof window.socketIO !== 'undefined')
{
window.socketIO.emit(e, obj);
}
}

Related

Convert xml to json in javascript or d3.js [duplicate]

How would you convert from XML to JSON and then back to XML?
The following tools work quite well, but aren't completely consistent:
xml2json
Has anyone encountered this situation before?
I think this is the best one: Converting between XML and JSON
Be sure to read the accompanying article on the xml.com O'Reilly site, which goes into details of the problems with these conversions, which I think you will find enlightening. The fact that O'Reilly is hosting the article should indicate that Stefan's solution has merit.
https://github.com/abdmob/x2js - my own library (updated URL from http://code.google.com/p/x2js/):
This library provides XML to JSON (JavaScript Objects) and vice versa javascript conversion functions. The library is very small and doesn't require any other additional libraries.
API functions
new X2JS() - to create your instance to access all library functionality. Also you could specify optional configuration options here
X2JS.xml2json - Convert XML specified as DOM Object to JSON
X2JS.json2xml - Convert JSON to XML DOM Object
X2JS.xml_str2json - Convert XML specified as string to JSON
X2JS.json2xml_str - Convert JSON to XML string
Online Demo on http://jsfiddle.net/abdmob/gkxucxrj/1/
var x2js = new X2JS();
function convertXml2JSon() {
$("#jsonArea").val(JSON.stringify(x2js.xml_str2json($("#xmlArea").val())));
}
function convertJSon2XML() {
$("#xmlArea").val(x2js.json2xml_str($.parseJSON($("#jsonArea").val())));
}
convertXml2JSon();
convertJSon2XML();
$("#convertToJsonBtn").click(convertXml2JSon);
$("#convertToXmlBtn").click(convertJSon2XML);
These answers helped me a lot to make this function:
function xml2json(xml) {
try {
var obj = {};
if (xml.children.length > 0) {
for (var i = 0; i < xml.children.length; i++) {
var item = xml.children.item(i);
var nodeName = item.nodeName;
if (typeof (obj[nodeName]) == "undefined") {
obj[nodeName] = xml2json(item);
} else {
if (typeof (obj[nodeName].push) == "undefined") {
var old = obj[nodeName];
obj[nodeName] = [];
obj[nodeName].push(old);
}
obj[nodeName].push(xml2json(item));
}
}
} else {
obj = xml.textContent;
}
return obj;
} catch (e) {
console.log(e.message);
}
}
As long as you pass in a jquery dom/xml object: for me it was:
Jquery(this).find('content').eq(0)[0]
where content was the field I was storing my xml in.
I've created a recursive function based on regex, in case you don't want to install library and understand the logic behind what's happening:
const xmlSample = '<tag>tag content</tag><tag2>another content</tag2><tag3><insideTag>inside content</insideTag><emptyTag /></tag3>';
console.log(parseXmlToJson(xmlSample));
function parseXmlToJson(xml) {
const json = {};
for (const res of xml.matchAll(/(?:<(\w*)(?:\s[^>]*)*>)((?:(?!<\1).)*)(?:<\/\1>)|<(\w*)(?:\s*)*\/>/gm)) {
const key = res[1] || res[3];
const value = res[2] && parseXmlToJson(res[2]);
json[key] = ((value && Object.keys(value).length) ? value : res[2]) || null;
}
return json;
}
Regex explanation for each loop:
res[0] - return the xml (as is)
res[1] - return the xml tag name
res[2] - return the xml content
res[3] - return the xml tag name in case the tag closes itself. In example: <tag />
You can check how the regex works here:
https://regex101.com/r/ZJpCAL/1
Note: In case json has a key with an undefined value, it is being removed.
That's why I've inserted null at the end of line 9.
I was using xmlToJson just to get a single value of the xml.
I found doing the following is much easier (if the xml only occurs once..)
let xml =
'<person>' +
' <id>762384324</id>' +
' <firstname>Hank</firstname> ' +
' <lastname>Stone</lastname>' +
'</person>';
let getXmlValue = function(str, key) {
return str.substring(
str.lastIndexOf('<' + key + '>') + ('<' + key + '>').length,
str.lastIndexOf('</' + key + '>')
);
}
alert(getXmlValue(xml, 'firstname')); // gives back Hank
You can also use txml. It can parse into a DOM made of simple objects and stringify. In the result, the content will be trimmed. So formating of the original with whitespaces will be lost. But this could be used very good to minify HTML.
const xml = require('txml');
const data = `
<tag>tag content</tag>
<tag2>another content</tag2>
<tag3>
<insideTag>inside content</insideTag>
<emptyTag />
</tag3>`;
const dom = xml(data); // the dom can be JSON.stringified
xml.stringify(dom); // this will return the dom into an xml-string
Disclaimer: I am the author of txml, the fastest xml parser in javascript.
A while back I wrote this tool https://bitbucket.org/surenrao/xml2json for my TV Watchlist app, hope this helps too.
Synopsys: A library to not only convert xml to json, but is also easy to debug (without circular errors) and recreate json back to xml. Features :- Parse xml to json object. Print json object back to xml. Can be used to save xml in IndexedDB as X2J objects. Print json object.
In 6 simple ES6 lines:
xml2json = xml => {
var el = xml.nodeType === 9 ? xml.documentElement : xml
var h = {name: el.nodeName}
h.content = Array.from(el.childNodes || []).filter(e => e.nodeType === 3).map(e => e.textContent).join('').trim()
h.attributes = Array.from(el.attributes || []).filter(a => a).reduce((h, a) => { h[a.name] = a.value; return h }, {})
h.children = Array.from(el.childNodes || []).filter(e => e.nodeType === 1).map(c => h[c.nodeName] = xml2json(c))
return h
}
Test with echo "xml2json_example()" | node -r xml2json.es6 with source at https://github.com/brauliobo/biochemical-db/blob/master/lib/xml2json.es6
Disclaimer: I've written fast-xml-parser
Fast XML Parser can help to convert XML to JSON and vice versa. Here is the example;
var options = {
attributeNamePrefix : "#_",
attrNodeName: "attr", //default is 'false'
textNodeName : "#text",
ignoreAttributes : true,
ignoreNameSpace : false,
allowBooleanAttributes : false,
parseNodeValue : true,
parseAttributeValue : false,
trimValues: true,
decodeHTMLchar: false,
cdataTagName: "__cdata", //default is 'false'
cdataPositionChar: "\\c",
};
if(parser.validate(xmlData)=== true){//optional
var jsonObj = parser.parse(xmlData,options);
}
If you want to parse JSON or JS object into XML then
//default options need not to set
var defaultOptions = {
attributeNamePrefix : "#_",
attrNodeName: "#", //default is false
textNodeName : "#text",
ignoreAttributes : true,
encodeHTMLchar: false,
cdataTagName: "__cdata", //default is false
cdataPositionChar: "\\c",
format: false,
indentBy: " ",
supressEmptyNode: false
};
var parser = new parser.j2xParser(defaultOptions);
var xml = parser.parse(json_or_js_obj);
Here' a good tool from a documented and very famous npm library that does the xml <-> js conversions very well: differently from some (maybe all) of the above proposed solutions, it converts xml comments also.
var obj = {name: "Super", Surname: "Man", age: 23};
var builder = new xml2js.Builder();
var xml = builder.buildObject(obj);
I would personally recommend this tool. It is an XML to JSON converter.
It is very lightweight and is in pure JavaScript. It needs no dependencies. You can simply add the functions to your code and use it as you wish.
It also takes the XML attributes into considerations.
var xml = ‘<person id=”1234” age=”30”><name>John Doe</name></person>’;
var json = xml2json(xml);
console.log(json);
// prints ‘{“person”: {“id”: “1234”, “age”: “30”, “name”: “John Doe”}}’
Here's an online demo!
There is an open sourced library Xml-to-json with methods jsonToXml(json) and xmlToJson(xml).
Here's an online demo!
This function directly reads the DOM properties of the XMLDocument (or document node/element) to build the JSON completely and accurately without trying to guess or match. Pass it responseXML, not responseText from XMLHttpRequest.
xml2json(xmlDoc)
If you only have a string of XML and not an XMLDocument, jQuery will convert your text to one.
xml2json($(xmlString)[0])
Each node becomes an object. (All elements are nodes, not all nodes are elements (e.g. text within an element).)
Every object contains the node name and type.
If it has attributes, they appear as properties in an attributes object.
If it has children, they appear recursively as node->objects in a children array.
If it's a Text, CDATA, or Comment node (bare text between element tags) or a comment, it shouldn't have attributes or children but the text will be in a text property.
{
// Always present
"name": "FancyElement",
"type": "Element",
// If present
"attributes: {
"attr1": "val1",
"attr2": "val2"
},
"children": [...],
"text": "buncha fancy words"
}
Caveat: I'm not familiar with all the node types. It's probably not grabbing needed/useful info from all of them. It was tested on and behaves as expected for
Element
Text
CDATA
Comment
Document
function xml2json(xml) {
try {
const types = [null,
"Element",
"Attribute",
"Text",
"CDATA",
"EntityReference", // Deprecated
"Entity", // Deprecated
"ProcessingInstruction",
"Comment",
"Document",
"DocumentType",
"DocumentFragment",
"Notation" // Deprecated
];
var o = {};
o.name = xml.nodeName;
o.type = types[xml.nodeType];
if (xml.nodeType == 3 ||
xml.nodeType == 4 ||
xml.nodeType == 8 ) {
o.text = xml.textContent;
} else {
if (xml.attributes) {
o.attributes = {};
for (const a of xml.attributes) {
o.attributes[a.name] = a.value;
}
}
if (xml.childNodes.length) {
o.children = [];
for (const x of xml.childNodes) {
o.children.push(xml2json(x))
}
}
}
return (o);
} catch (e) {
alert('Error in xml2json. See console for details.');
console.log('Error in xml2json processing node:');
console.log(o);
console.log('Error:');
console.log(e);
}
}
var doc = document.getElementById("doc");
var out = document.getElementById("out");
out.innerText = JSON.stringify(xml2json(doc), null, 2);
/* Let's process the whole Code Snippet #document, why not?
* Yes, the JSON we just put in the document body and all
* this code is encoded in the JSON in the console.
* In that copy you can see why the XML DOM will all be one line.
* The JSON in the console has "\n" nodes all throughout.
*/
console.log(xml2json(document));
#doc,
#out {
border: 1px solid black;
}
<div id="doc"><!-- The XML DOM will all be on one line --><div personality="bubbly" relevance=42>This text is valid for HTML.<span>But it probably shouldn't be siblings to an element in XML.</span></div></div>
<pre id="out"></pre>
The best way to do it using server side as client side doesn't work well in all scenarios. I was trying to build online json to xml and xml to json converter using javascript and I felt almost impossible as it was not working in all scenarios. Ultimately I ended up doing it server side using Newtonsoft in ASP.MVC. Here is the online converter http://techfunda.com/Tools/XmlToJson

How to convert JSON to XML? [duplicate]

How would you convert from XML to JSON and then back to XML?
The following tools work quite well, but aren't completely consistent:
xml2json
Has anyone encountered this situation before?
I think this is the best one: Converting between XML and JSON
Be sure to read the accompanying article on the xml.com O'Reilly site, which goes into details of the problems with these conversions, which I think you will find enlightening. The fact that O'Reilly is hosting the article should indicate that Stefan's solution has merit.
https://github.com/abdmob/x2js - my own library (updated URL from http://code.google.com/p/x2js/):
This library provides XML to JSON (JavaScript Objects) and vice versa javascript conversion functions. The library is very small and doesn't require any other additional libraries.
API functions
new X2JS() - to create your instance to access all library functionality. Also you could specify optional configuration options here
X2JS.xml2json - Convert XML specified as DOM Object to JSON
X2JS.json2xml - Convert JSON to XML DOM Object
X2JS.xml_str2json - Convert XML specified as string to JSON
X2JS.json2xml_str - Convert JSON to XML string
Online Demo on http://jsfiddle.net/abdmob/gkxucxrj/1/
var x2js = new X2JS();
function convertXml2JSon() {
$("#jsonArea").val(JSON.stringify(x2js.xml_str2json($("#xmlArea").val())));
}
function convertJSon2XML() {
$("#xmlArea").val(x2js.json2xml_str($.parseJSON($("#jsonArea").val())));
}
convertXml2JSon();
convertJSon2XML();
$("#convertToJsonBtn").click(convertXml2JSon);
$("#convertToXmlBtn").click(convertJSon2XML);
These answers helped me a lot to make this function:
function xml2json(xml) {
try {
var obj = {};
if (xml.children.length > 0) {
for (var i = 0; i < xml.children.length; i++) {
var item = xml.children.item(i);
var nodeName = item.nodeName;
if (typeof (obj[nodeName]) == "undefined") {
obj[nodeName] = xml2json(item);
} else {
if (typeof (obj[nodeName].push) == "undefined") {
var old = obj[nodeName];
obj[nodeName] = [];
obj[nodeName].push(old);
}
obj[nodeName].push(xml2json(item));
}
}
} else {
obj = xml.textContent;
}
return obj;
} catch (e) {
console.log(e.message);
}
}
As long as you pass in a jquery dom/xml object: for me it was:
Jquery(this).find('content').eq(0)[0]
where content was the field I was storing my xml in.
I've created a recursive function based on regex, in case you don't want to install library and understand the logic behind what's happening:
const xmlSample = '<tag>tag content</tag><tag2>another content</tag2><tag3><insideTag>inside content</insideTag><emptyTag /></tag3>';
console.log(parseXmlToJson(xmlSample));
function parseXmlToJson(xml) {
const json = {};
for (const res of xml.matchAll(/(?:<(\w*)(?:\s[^>]*)*>)((?:(?!<\1).)*)(?:<\/\1>)|<(\w*)(?:\s*)*\/>/gm)) {
const key = res[1] || res[3];
const value = res[2] && parseXmlToJson(res[2]);
json[key] = ((value && Object.keys(value).length) ? value : res[2]) || null;
}
return json;
}
Regex explanation for each loop:
res[0] - return the xml (as is)
res[1] - return the xml tag name
res[2] - return the xml content
res[3] - return the xml tag name in case the tag closes itself. In example: <tag />
You can check how the regex works here:
https://regex101.com/r/ZJpCAL/1
Note: In case json has a key with an undefined value, it is being removed.
That's why I've inserted null at the end of line 9.
I was using xmlToJson just to get a single value of the xml.
I found doing the following is much easier (if the xml only occurs once..)
let xml =
'<person>' +
' <id>762384324</id>' +
' <firstname>Hank</firstname> ' +
' <lastname>Stone</lastname>' +
'</person>';
let getXmlValue = function(str, key) {
return str.substring(
str.lastIndexOf('<' + key + '>') + ('<' + key + '>').length,
str.lastIndexOf('</' + key + '>')
);
}
alert(getXmlValue(xml, 'firstname')); // gives back Hank
You can also use txml. It can parse into a DOM made of simple objects and stringify. In the result, the content will be trimmed. So formating of the original with whitespaces will be lost. But this could be used very good to minify HTML.
const xml = require('txml');
const data = `
<tag>tag content</tag>
<tag2>another content</tag2>
<tag3>
<insideTag>inside content</insideTag>
<emptyTag />
</tag3>`;
const dom = xml(data); // the dom can be JSON.stringified
xml.stringify(dom); // this will return the dom into an xml-string
Disclaimer: I am the author of txml, the fastest xml parser in javascript.
A while back I wrote this tool https://bitbucket.org/surenrao/xml2json for my TV Watchlist app, hope this helps too.
Synopsys: A library to not only convert xml to json, but is also easy to debug (without circular errors) and recreate json back to xml. Features :- Parse xml to json object. Print json object back to xml. Can be used to save xml in IndexedDB as X2J objects. Print json object.
In 6 simple ES6 lines:
xml2json = xml => {
var el = xml.nodeType === 9 ? xml.documentElement : xml
var h = {name: el.nodeName}
h.content = Array.from(el.childNodes || []).filter(e => e.nodeType === 3).map(e => e.textContent).join('').trim()
h.attributes = Array.from(el.attributes || []).filter(a => a).reduce((h, a) => { h[a.name] = a.value; return h }, {})
h.children = Array.from(el.childNodes || []).filter(e => e.nodeType === 1).map(c => h[c.nodeName] = xml2json(c))
return h
}
Test with echo "xml2json_example()" | node -r xml2json.es6 with source at https://github.com/brauliobo/biochemical-db/blob/master/lib/xml2json.es6
Disclaimer: I've written fast-xml-parser
Fast XML Parser can help to convert XML to JSON and vice versa. Here is the example;
var options = {
attributeNamePrefix : "#_",
attrNodeName: "attr", //default is 'false'
textNodeName : "#text",
ignoreAttributes : true,
ignoreNameSpace : false,
allowBooleanAttributes : false,
parseNodeValue : true,
parseAttributeValue : false,
trimValues: true,
decodeHTMLchar: false,
cdataTagName: "__cdata", //default is 'false'
cdataPositionChar: "\\c",
};
if(parser.validate(xmlData)=== true){//optional
var jsonObj = parser.parse(xmlData,options);
}
If you want to parse JSON or JS object into XML then
//default options need not to set
var defaultOptions = {
attributeNamePrefix : "#_",
attrNodeName: "#", //default is false
textNodeName : "#text",
ignoreAttributes : true,
encodeHTMLchar: false,
cdataTagName: "__cdata", //default is false
cdataPositionChar: "\\c",
format: false,
indentBy: " ",
supressEmptyNode: false
};
var parser = new parser.j2xParser(defaultOptions);
var xml = parser.parse(json_or_js_obj);
Here' a good tool from a documented and very famous npm library that does the xml <-> js conversions very well: differently from some (maybe all) of the above proposed solutions, it converts xml comments also.
var obj = {name: "Super", Surname: "Man", age: 23};
var builder = new xml2js.Builder();
var xml = builder.buildObject(obj);
I would personally recommend this tool. It is an XML to JSON converter.
It is very lightweight and is in pure JavaScript. It needs no dependencies. You can simply add the functions to your code and use it as you wish.
It also takes the XML attributes into considerations.
var xml = ‘<person id=”1234” age=”30”><name>John Doe</name></person>’;
var json = xml2json(xml);
console.log(json);
// prints ‘{“person”: {“id”: “1234”, “age”: “30”, “name”: “John Doe”}}’
Here's an online demo!
There is an open sourced library Xml-to-json with methods jsonToXml(json) and xmlToJson(xml).
Here's an online demo!
This function directly reads the DOM properties of the XMLDocument (or document node/element) to build the JSON completely and accurately without trying to guess or match. Pass it responseXML, not responseText from XMLHttpRequest.
xml2json(xmlDoc)
If you only have a string of XML and not an XMLDocument, jQuery will convert your text to one.
xml2json($(xmlString)[0])
Each node becomes an object. (All elements are nodes, not all nodes are elements (e.g. text within an element).)
Every object contains the node name and type.
If it has attributes, they appear as properties in an attributes object.
If it has children, they appear recursively as node->objects in a children array.
If it's a Text, CDATA, or Comment node (bare text between element tags) or a comment, it shouldn't have attributes or children but the text will be in a text property.
{
// Always present
"name": "FancyElement",
"type": "Element",
// If present
"attributes: {
"attr1": "val1",
"attr2": "val2"
},
"children": [...],
"text": "buncha fancy words"
}
Caveat: I'm not familiar with all the node types. It's probably not grabbing needed/useful info from all of them. It was tested on and behaves as expected for
Element
Text
CDATA
Comment
Document
function xml2json(xml) {
try {
const types = [null,
"Element",
"Attribute",
"Text",
"CDATA",
"EntityReference", // Deprecated
"Entity", // Deprecated
"ProcessingInstruction",
"Comment",
"Document",
"DocumentType",
"DocumentFragment",
"Notation" // Deprecated
];
var o = {};
o.name = xml.nodeName;
o.type = types[xml.nodeType];
if (xml.nodeType == 3 ||
xml.nodeType == 4 ||
xml.nodeType == 8 ) {
o.text = xml.textContent;
} else {
if (xml.attributes) {
o.attributes = {};
for (const a of xml.attributes) {
o.attributes[a.name] = a.value;
}
}
if (xml.childNodes.length) {
o.children = [];
for (const x of xml.childNodes) {
o.children.push(xml2json(x))
}
}
}
return (o);
} catch (e) {
alert('Error in xml2json. See console for details.');
console.log('Error in xml2json processing node:');
console.log(o);
console.log('Error:');
console.log(e);
}
}
var doc = document.getElementById("doc");
var out = document.getElementById("out");
out.innerText = JSON.stringify(xml2json(doc), null, 2);
/* Let's process the whole Code Snippet #document, why not?
* Yes, the JSON we just put in the document body and all
* this code is encoded in the JSON in the console.
* In that copy you can see why the XML DOM will all be one line.
* The JSON in the console has "\n" nodes all throughout.
*/
console.log(xml2json(document));
#doc,
#out {
border: 1px solid black;
}
<div id="doc"><!-- The XML DOM will all be on one line --><div personality="bubbly" relevance=42>This text is valid for HTML.<span>But it probably shouldn't be siblings to an element in XML.</span></div></div>
<pre id="out"></pre>
The best way to do it using server side as client side doesn't work well in all scenarios. I was trying to build online json to xml and xml to json converter using javascript and I felt almost impossible as it was not working in all scenarios. Ultimately I ended up doing it server side using Newtonsoft in ASP.MVC. Here is the online converter http://techfunda.com/Tools/XmlToJson

data cleansing javascript objects

I have a http server built in node.js and 'connect'. The web service currently parses JSON requests to an Object, does "stuff", and returns a synchronous response. The JSON is from an ecommerce cart and I end up with an Object that looks like (abridged version):
var myObj = {"request":{"industry":"social","transactionId":"gdfs23s","billing": {"addressLine1":"911 Fallen Street","addressLine2":"1 2"},"shipping":{"addressLine1":"1523 Willow Tree LAne","addressLine2":"unit 15"}}}
I want to clean up the data, performing tasks such as removing extra white space, normalizing postal abbreviation, ie street to st, etc.
I've written a series of regular expression that successfully achieve the cleansing/normalization.
However what I am unsure of is how to do this efficiently AND elegantly apply these cleanse processes to an Object in JS /Node.js. I will have scenarios where I want to cleanse request.billing.addressLine1, request.shipping.addressLine1 with the same regex pattern
I could of course do something like:
var addressCleaner= new RegExp("( str| street| strt)","g");
myObj.request.billing.addressLine1.replace(addressCleaner, "st");
myObj.request.shipping.addressLine1.replace(addressCleaner, "st");
But I dont feel this is very DRY and furthermore its not being done very "node"ishly.
Any suggestions or example approaches? I would like to avoid using a package like Mongoose etc. to do this as the type of normalizing i'm doing does not just consist of making sure a string is a string ,etc.
Thanks in advance.
So, I would suggest to have a hash with all normalizers, and seperately to have a list of properties,
which needs to be normalized. To have the idea here some code:
var Normalizers = {
// -> function
trim: function(str) { return str.trim(); },
// -> array [RegExp, StringToReplace]
street: [ /(str|street)/g, 'st']
//...
};
var properties = {
'request.billing.addressLine1': ['trim', 'street'],
// ..
};
obj_normalize(myObj, properties, Normalizers);
The code for obj_normalize/obj_getProprety/obj_setProperty I moved to the gist.
If your regex is applicable to every string found within the object you can simply recurse through the object and apply the regex to every string.
A general purpose object traversal function is very useful for something like this:
function object_traverse (name,obj,fn) {
obj = fn(name,obj);
if (obj instanceof Array) {
for (var n=0;n<obj.length;n++) {
obj[n] = object_traverse(n,obj[n],fn);
}
}
else if (typeof obj != "string" && typeof obj != "number") {
for (var n in obj) {
obj[n] = object_traverse(n,obj[n],fn);
}
}
return obj;
}
Now you can do this:
myObj = object_traverse('',myObj,function(name,obj){
if (typeof obj == "string" && name.match(/address/i)) {
obj = obj.replace(addressCleaner, "st");
}
return obj;
});
I'd have a model built from JSON files and serialize it as I see fit. This would avoid matching or searching for properties which couldn't possibly exist in the source. Some example:
function makeAddress(rawAddress) {
return { street: rawAddress["str"] ||
rawAddress["street"] ||
rawAddress["strt"],
. . . };
Being equipped with this function, say, then you have an array of "address" object, then converting them would be a matter of:
addresses.map(makeAddress);

Custom object to JSON then back to a custom object?

I've seen very similar questions to this, but I can't quite decide if they was answered clearly - maybe I'm being a bit dense, sorry.
I want to have the convenience (and clarity) of my own object, call it a CardboardBox(). It won't contain code, just data. I want to write this to a database and read it back later, but obviously, it is a type Object() when it's read back. All I can think of to find out what it used to be is:
Have a member variable type that I set to CARDBOARD_BOX
Instantiate a new CarbardBox() and use a function (in the box) to copy the properties of Object() to the new CardboardBox() object
Is there a better way of doing this? I'm pretty sure I can change the actual type.
function CardboardBox() {
this.type = "CARDBOARD_BOX"
this.name = "No set";
this.populate = new function(obj) {
// populate this object with obj properties
}
var box = new CarboardBox(); // CarboardBox
box.name = "My Box";
send = JSON.stringyfy(box);
.
.
.
obj = JSON.parse(send); // Object
if (obj.type == "CARDBOARD_BOX") {
savedBox = new CardboardBox();
savedBox.populate(obj);
}
Thanks in advance...
Steve
[edit] My test code.
function CardboardBox(n) {
this.name = n;
}
var box = new CardboardBox("My Box");
send = JSON.stringify(box); // JSON CarboardBox()
obj = JSON.parse(send, function fn(obj) { // Object() returned
log("OB: "+obj.type);
return obj.type === 'CardboardBox' ? new CardboardBox(obj) : CardboardBox;
});
console.log(obj);
Output is:
OB: undefined utils.js:40
OB: undefined utils.js:40
function CardboardBox(n) {
this.name = n;
}
One possible solution is the following:
function CardboardBox(n) {
if(typeof(n) == 'string') {
//build from name string
this.name = n;
} else {
//build from object
this.name = n.name;
}
//add in this object's "type" in a place
//that is unlikely to exist in other JSON strings
this.__type = 'CardboardBox';
}
var box = new CardboardBox("My Box");
send = JSON.stringify(box), // JSON CarboardBox()
obj = JSON.parse(send, function(key, val) {
//if this is an object, and is CardboardBox
if(typeof(val) === 'object' && val.__type === 'CardboardBox')
return new CardboardBox(val);
return val;
//or if your object is in a context (like window), and there are many of
//them that could be in there, you can do:
//
//if(typeof(val) === 'object' && context[val.__type])
// return new context[val.__type](val);
});
console.log(obj);
Basically store the object type in a place you know to look for later on when parsing the json. if you have multiple objects you can instantiate in a single scope the second parse method may be more appropriate. This also will account for objects in the JSON that are not CarboardBoxs.
Edit Here is a jsFiddle of this method in action.
Overall, you're correct: Javascript doesn't have any built-in way to serialize anything beyond plain objects, so going to and from JSON will not produce a particular class when you deserialize it. So you need to either work out serialization/deserialization yourself, or use a library that provides some support.
I personally like Backbone.js for this problem, as it handles serializing and deserializing quite well. You define a model class, which include a method to save its data to a server in a serialized form, and a method to deserialize it back to the model. The key design issue here is that deserializing is performed knowing the model you're deserializing to:
you either call myModel.fetch() to get data from the server based on the model id, or
you pass a bunch of new data to the model constructor: new Model(serializedData), or
you pass an array of data for multiple models to a collection that knows the model type: new ModelCollection(arrayOfSerializedData).
What Backbone doesn't do is deal with type-casting data of an unknown type. When I've dealt with this, I've usually done something similar to #Chad's response, but using an intermediary; you could see this as a proxy model, or as a factory:
var classes = {
CardboardBox: ...,
AluminumBox: ...
}
function Deserializer(json) {
// parse if you're actually dealing with a string
var data = JSON.parse(json),
// now look for some custom type flag - you'll need to set this yourself
type = data.type,
// class lookup, perhaps with a default
Cls = classes[type] || DefaultType;
return new Cls(data);
}
var obj = new Deserializer(send);
obj instanceof CardboardBox; // should work
This still relies on a custom flag to switch types, though - I'm not sure there's any way around this.

Convert XML to JSON (and back) using Javascript

How would you convert from XML to JSON and then back to XML?
The following tools work quite well, but aren't completely consistent:
xml2json
Has anyone encountered this situation before?
I think this is the best one: Converting between XML and JSON
Be sure to read the accompanying article on the xml.com O'Reilly site, which goes into details of the problems with these conversions, which I think you will find enlightening. The fact that O'Reilly is hosting the article should indicate that Stefan's solution has merit.
https://github.com/abdmob/x2js - my own library (updated URL from http://code.google.com/p/x2js/):
This library provides XML to JSON (JavaScript Objects) and vice versa javascript conversion functions. The library is very small and doesn't require any other additional libraries.
API functions
new X2JS() - to create your instance to access all library functionality. Also you could specify optional configuration options here
X2JS.xml2json - Convert XML specified as DOM Object to JSON
X2JS.json2xml - Convert JSON to XML DOM Object
X2JS.xml_str2json - Convert XML specified as string to JSON
X2JS.json2xml_str - Convert JSON to XML string
Online Demo on http://jsfiddle.net/abdmob/gkxucxrj/1/
var x2js = new X2JS();
function convertXml2JSon() {
$("#jsonArea").val(JSON.stringify(x2js.xml_str2json($("#xmlArea").val())));
}
function convertJSon2XML() {
$("#xmlArea").val(x2js.json2xml_str($.parseJSON($("#jsonArea").val())));
}
convertXml2JSon();
convertJSon2XML();
$("#convertToJsonBtn").click(convertXml2JSon);
$("#convertToXmlBtn").click(convertJSon2XML);
These answers helped me a lot to make this function:
function xml2json(xml) {
try {
var obj = {};
if (xml.children.length > 0) {
for (var i = 0; i < xml.children.length; i++) {
var item = xml.children.item(i);
var nodeName = item.nodeName;
if (typeof (obj[nodeName]) == "undefined") {
obj[nodeName] = xml2json(item);
} else {
if (typeof (obj[nodeName].push) == "undefined") {
var old = obj[nodeName];
obj[nodeName] = [];
obj[nodeName].push(old);
}
obj[nodeName].push(xml2json(item));
}
}
} else {
obj = xml.textContent;
}
return obj;
} catch (e) {
console.log(e.message);
}
}
As long as you pass in a jquery dom/xml object: for me it was:
Jquery(this).find('content').eq(0)[0]
where content was the field I was storing my xml in.
I've created a recursive function based on regex, in case you don't want to install library and understand the logic behind what's happening:
const xmlSample = '<tag>tag content</tag><tag2>another content</tag2><tag3><insideTag>inside content</insideTag><emptyTag /></tag3>';
console.log(parseXmlToJson(xmlSample));
function parseXmlToJson(xml) {
const json = {};
for (const res of xml.matchAll(/(?:<(\w*)(?:\s[^>]*)*>)((?:(?!<\1).)*)(?:<\/\1>)|<(\w*)(?:\s*)*\/>/gm)) {
const key = res[1] || res[3];
const value = res[2] && parseXmlToJson(res[2]);
json[key] = ((value && Object.keys(value).length) ? value : res[2]) || null;
}
return json;
}
Regex explanation for each loop:
res[0] - return the xml (as is)
res[1] - return the xml tag name
res[2] - return the xml content
res[3] - return the xml tag name in case the tag closes itself. In example: <tag />
You can check how the regex works here:
https://regex101.com/r/ZJpCAL/1
Note: In case json has a key with an undefined value, it is being removed.
That's why I've inserted null at the end of line 9.
I was using xmlToJson just to get a single value of the xml.
I found doing the following is much easier (if the xml only occurs once..)
let xml =
'<person>' +
' <id>762384324</id>' +
' <firstname>Hank</firstname> ' +
' <lastname>Stone</lastname>' +
'</person>';
let getXmlValue = function(str, key) {
return str.substring(
str.lastIndexOf('<' + key + '>') + ('<' + key + '>').length,
str.lastIndexOf('</' + key + '>')
);
}
alert(getXmlValue(xml, 'firstname')); // gives back Hank
You can also use txml. It can parse into a DOM made of simple objects and stringify. In the result, the content will be trimmed. So formating of the original with whitespaces will be lost. But this could be used very good to minify HTML.
const xml = require('txml');
const data = `
<tag>tag content</tag>
<tag2>another content</tag2>
<tag3>
<insideTag>inside content</insideTag>
<emptyTag />
</tag3>`;
const dom = xml(data); // the dom can be JSON.stringified
xml.stringify(dom); // this will return the dom into an xml-string
Disclaimer: I am the author of txml, the fastest xml parser in javascript.
A while back I wrote this tool https://bitbucket.org/surenrao/xml2json for my TV Watchlist app, hope this helps too.
Synopsys: A library to not only convert xml to json, but is also easy to debug (without circular errors) and recreate json back to xml. Features :- Parse xml to json object. Print json object back to xml. Can be used to save xml in IndexedDB as X2J objects. Print json object.
In 6 simple ES6 lines:
xml2json = xml => {
var el = xml.nodeType === 9 ? xml.documentElement : xml
var h = {name: el.nodeName}
h.content = Array.from(el.childNodes || []).filter(e => e.nodeType === 3).map(e => e.textContent).join('').trim()
h.attributes = Array.from(el.attributes || []).filter(a => a).reduce((h, a) => { h[a.name] = a.value; return h }, {})
h.children = Array.from(el.childNodes || []).filter(e => e.nodeType === 1).map(c => h[c.nodeName] = xml2json(c))
return h
}
Test with echo "xml2json_example()" | node -r xml2json.es6 with source at https://github.com/brauliobo/biochemical-db/blob/master/lib/xml2json.es6
Disclaimer: I've written fast-xml-parser
Fast XML Parser can help to convert XML to JSON and vice versa. Here is the example;
var options = {
attributeNamePrefix : "#_",
attrNodeName: "attr", //default is 'false'
textNodeName : "#text",
ignoreAttributes : true,
ignoreNameSpace : false,
allowBooleanAttributes : false,
parseNodeValue : true,
parseAttributeValue : false,
trimValues: true,
decodeHTMLchar: false,
cdataTagName: "__cdata", //default is 'false'
cdataPositionChar: "\\c",
};
if(parser.validate(xmlData)=== true){//optional
var jsonObj = parser.parse(xmlData,options);
}
If you want to parse JSON or JS object into XML then
//default options need not to set
var defaultOptions = {
attributeNamePrefix : "#_",
attrNodeName: "#", //default is false
textNodeName : "#text",
ignoreAttributes : true,
encodeHTMLchar: false,
cdataTagName: "__cdata", //default is false
cdataPositionChar: "\\c",
format: false,
indentBy: " ",
supressEmptyNode: false
};
var parser = new parser.j2xParser(defaultOptions);
var xml = parser.parse(json_or_js_obj);
Here' a good tool from a documented and very famous npm library that does the xml <-> js conversions very well: differently from some (maybe all) of the above proposed solutions, it converts xml comments also.
var obj = {name: "Super", Surname: "Man", age: 23};
var builder = new xml2js.Builder();
var xml = builder.buildObject(obj);
I would personally recommend this tool. It is an XML to JSON converter.
It is very lightweight and is in pure JavaScript. It needs no dependencies. You can simply add the functions to your code and use it as you wish.
It also takes the XML attributes into considerations.
var xml = ‘<person id=”1234” age=”30”><name>John Doe</name></person>’;
var json = xml2json(xml);
console.log(json);
// prints ‘{“person”: {“id”: “1234”, “age”: “30”, “name”: “John Doe”}}’
Here's an online demo!
There is an open sourced library Xml-to-json with methods jsonToXml(json) and xmlToJson(xml).
Here's an online demo!
This function directly reads the DOM properties of the XMLDocument (or document node/element) to build the JSON completely and accurately without trying to guess or match. Pass it responseXML, not responseText from XMLHttpRequest.
xml2json(xmlDoc)
If you only have a string of XML and not an XMLDocument, jQuery will convert your text to one.
xml2json($(xmlString)[0])
Each node becomes an object. (All elements are nodes, not all nodes are elements (e.g. text within an element).)
Every object contains the node name and type.
If it has attributes, they appear as properties in an attributes object.
If it has children, they appear recursively as node->objects in a children array.
If it's a Text, CDATA, or Comment node (bare text between element tags) or a comment, it shouldn't have attributes or children but the text will be in a text property.
{
// Always present
"name": "FancyElement",
"type": "Element",
// If present
"attributes: {
"attr1": "val1",
"attr2": "val2"
},
"children": [...],
"text": "buncha fancy words"
}
Caveat: I'm not familiar with all the node types. It's probably not grabbing needed/useful info from all of them. It was tested on and behaves as expected for
Element
Text
CDATA
Comment
Document
function xml2json(xml) {
try {
const types = [null,
"Element",
"Attribute",
"Text",
"CDATA",
"EntityReference", // Deprecated
"Entity", // Deprecated
"ProcessingInstruction",
"Comment",
"Document",
"DocumentType",
"DocumentFragment",
"Notation" // Deprecated
];
var o = {};
o.name = xml.nodeName;
o.type = types[xml.nodeType];
if (xml.nodeType == 3 ||
xml.nodeType == 4 ||
xml.nodeType == 8 ) {
o.text = xml.textContent;
} else {
if (xml.attributes) {
o.attributes = {};
for (const a of xml.attributes) {
o.attributes[a.name] = a.value;
}
}
if (xml.childNodes.length) {
o.children = [];
for (const x of xml.childNodes) {
o.children.push(xml2json(x))
}
}
}
return (o);
} catch (e) {
alert('Error in xml2json. See console for details.');
console.log('Error in xml2json processing node:');
console.log(o);
console.log('Error:');
console.log(e);
}
}
var doc = document.getElementById("doc");
var out = document.getElementById("out");
out.innerText = JSON.stringify(xml2json(doc), null, 2);
/* Let's process the whole Code Snippet #document, why not?
* Yes, the JSON we just put in the document body and all
* this code is encoded in the JSON in the console.
* In that copy you can see why the XML DOM will all be one line.
* The JSON in the console has "\n" nodes all throughout.
*/
console.log(xml2json(document));
#doc,
#out {
border: 1px solid black;
}
<div id="doc"><!-- The XML DOM will all be on one line --><div personality="bubbly" relevance=42>This text is valid for HTML.<span>But it probably shouldn't be siblings to an element in XML.</span></div></div>
<pre id="out"></pre>
The best way to do it using server side as client side doesn't work well in all scenarios. I was trying to build online json to xml and xml to json converter using javascript and I felt almost impossible as it was not working in all scenarios. Ultimately I ended up doing it server side using Newtonsoft in ASP.MVC. Here is the online converter http://techfunda.com/Tools/XmlToJson

Categories