How i can make json child nodes (JSON inside JSON)? - javascript

I try to use the jquery + json to get all elements in form and build a JSON var to post in a ASP.NET MVC method.
$.fn.serializeObject = function () {
var o = {};
var a = this.serializeArray();
$.each(a, function () {
if (o[this.name]) {
if (!o[this.name].push) {
o[this.name] = [o[this.name]];
}
o[this.name].push(this.value || '');
} else {
o[this.name] = this.value || '';
}
});
return o;
};
$("#btnPost").click(function () {
alert(JSON.stringify($("#frm").serializeObject())));
});
It method get all fields in a form and build a JSON, but it dont put JSON inside JSON.
Example:
If i have the follow form:
<input name="person.name"><input name="person.age"><input name="person.address.street">
The serialized string build a JSON like this
{ "person.name": "??", "person.age": "??", "person.address.street": "??" }
I need a plugin or some function to generate like this:
{ "person": { "name" : "??", "age" : "??", "address":{ "street": "??" } } }

Your problem is not "JSON within JSON" (which is a misnomer anyway - JSON supports nesting just fine), your problem is you've misinterpreted how this process works.
Your serializeObject() method is just reading the names - as strings There's nothing in javascript that makes this process "automagically" resolve the dot-notation for you - the periods are just treated as part of the property name.
You'll need to split the names on the periods and proceed accordingly. A little dab of recursion and you're there.
$.fn.serializeObject = function()
{
var o = {};
var a = this.serializeArray();
$.each( a, function()
{
if ( /\./.test( this.name ) )
{
resolveProperty( o, this.name.split( '.' ), this.value );
} else {
o[this.name] = this.value;
}
} );
return o;
function resolveProperty( object, properties, value )
{
if ( properties.length > 1 )
{
var property = properties.shift();
if ( 'undefined' == typeof object[property] )
{
object[property] = {};
}
resolveProperty( object[property], properties, value );
} else {
object[properties.shift()] = value;
}
}
};

Related

How do you JSON (instead of serialize) a form that has name="Item[][things]" without obtaining an object with null children?

This is a pretty specific issue and I can't find it online or I couldn't find a solution to it until now at least.
I have a form, that contains inputs that have: name = "Item[][things]" as in an item. Can't change that. I want to turn that into a JSON to send it to the server. I can't use serialize, I really need to turn it into a JSON.
This doesn't work with what I tried: JSON.stringify($myForm.serializeObject()). Because my form contains name="Item[][differentOtherThings]", I get an array of nulls [null, null, ..., null]
I added a serializeObject() custom method jquery-serialize-object to my project.
Any ideas on how I could JSON the form without the null issue?
see the bellow snippet
$(function(){
$("#serialize").click(function(){
var $myForm = $("form").eq(0);
var str = JSON.stringify($myForm.serializeObject());
console.log(str);
var object = JSON.parse(str);
console.log(object);
})
});
$.fn.serializeObject = function()
{
var o = {};
var a = this.serializeArray();
$.each(a, function() {
if (o[this.name] !== undefined) {
if (!o[this.name].push) {
o[this.name] = [o[this.name]];
}
o[this.name].push(this.value || '');
} else {
o[this.name] = this.value || '';
}
});
return o;
};
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<form>
<p><input type="text" name = "Item[][things]"></p>
<p><input type="text" name = "Item[][things1]"></p>
<p><input type="text" name = "Item[][differentOtherThings]"></p>
</form>
<button id="serialize">serialize</button>

Javascript : How to concat string to object?

I have following code where i combine some variables to create path to the another existing object and his attribute.
Problem is that i alway get only string, so i would like to "convert" it into the object.
// SET CUSTOM CONTENT FOR COLUMN IF CONTACT ATTR IS EXISTS
if(value.concatByFields != null) {
preparedGridColumnItem.template = function (responseData) {
var nameForConcat;
var fieldName;
var objectName;
var pathToReturn;
$.each(value.concatByFields, function( index, concatField ) {
nameForConcat = null;
fieldName = null;
objectName = null;
objectName = value.field;
fieldName = concatField.fieldName;
console.log("FIELD NAME IS");
console.log(JSON.stringify(fieldName));
console.log("OBJECT NAME IS");
console.log(objectName);
nameForConcat = objectName+"."+fieldName;
console.log("CONCATED NAME IS");
console.log(nameForConcat);
console.log("OBJECT ADDRESS IS FOLLOWING");
console.log("responseData."+nameForConcat);
pathToReturn = "responseData."+nameForConcat;
});
//TODO : IS ALWAYS RETURNED AS STRING
return pathToReturn;
};
}
Returned value should be value of another and global existing json object. But now is it always string.
It means:
responseData.SomeObject.surname
How can i solve it please?
Many thanks for any help.
if(value.concatByFields != null) {
preparedGridColumnItem.template = function (responseData) {
var fieldName;
var objectName;
var pathToReturn;
$.each(value.concatByFields, function( index, concatField ) {
objectName = value.field;
fieldName = concatField.fieldName;
pathToReturn = responseData[objectName][fieldName];
});
//TODO : IS ALWAYS RETURNED AS STRING
return pathToReturn;
};
}

Javascript/jQuery search json for a string then run a function

I need to run a function matchFound() if a string is found in an external json file.
This is what I have so far:
function init(){
$.ajax({
type: "GET",
url: "http://ajax.googleapis.com/ajax/services/feed/load?v=1.0&num=50&callback=?&q=http://www.domain.com/feed.rss",
dataType: "json",
success: parseData
});
}
function parseData(data){
var string_to_find = "Hello World!";
// look into the data and match the string
}
function matchFound(str, string_to_find){
alert('Match found in string - '+ str +'\r\n While looking for the string- '+ string_to_find);
return true;
}
function matchNotFound(){
alert('No Match found!');
}
But I don't know how to parse the Json data and search for a string.
I have this for XML (thanks #Ohgodwhy) but not sure how to translate for json
function parseXml(xml){
var string_to_find = "Hello World!";
$(xml).find('title').each(function(){
var str = $(this).text();
if(str.indexOf(string_to_find) > -1){
if(matchFound(str, string_to_find)){
return false;
}
}
});
}
The search location within the variables is: responceData > feed > entries > [0] or 1 or [2] etc > contentSnippet
I only need to match the first 10 characters.
If a match is found then run the funciton matchFound() or if not found run the function matchNotFound()
Any help with this is very much appreciated.
C
you have to iterate json recursively and then search for the string
function parseData(data){
var string_to_find = "Hello World!";
var is_found = iterate(data , string_to_find);
if(is_found === true){
matchFound(JSON.stringify(data), string_to_find);
}else{
matchNotFound(string_to_find);
}
// look into the data and match the string
}
function iterate(obj , string_to_find) {
for(var key in obj) { // iterate, `key` is the property key
var elem = obj[key]; // `obj[key]` is the value
console.log(elem, string_to_find);
if(typeof(elem)=="string" && elem.indexOf(string_to_find)!==-1) {
return true;
}
if(typeof elem === "object") { // is an object (plain object or array),
// so contains children
return iterate(elem , string_to_find); // call recursively
}
}
}

Is there a Jquery function that can take a #ref id value from a parsed JSON string and point me to the referenced object?

I have been looking for an answer to this all afternoon and i cant seem to find the best way to accomplish what i need to.
My JSON string (returned from a web service) has circular references in it (#ref) which point to $id in the string. Now i know that if use jquery parseJSON it creates the javascript object and i can access properties a la myObject.MyPropertyName. However, when i get to a #ref, i am unsure how to get the object that ID points to (which i assume is already created as a result of the de-serialization...
Should i be iterating though the object and all its child objects until i find it, or is there an easier way?
$.ajax({
type: "POST",
url: "/Task.asmx/GetTask",
data: "{'id':'" + '27' + "'}",
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function (msg) {
_Data = $.parseJSON(msg.d ? msg.d : msg);
_this.Company = _Data[0].t_Program.t_Company;
_this.Program = _Data[0].t_Program;
_this.Task = _Data[0];
},
complete: function () {
}
});
The area in question is _Data[0].t_Program because it does not return an object but rather returns
_Data[0].t_Program
{...}
$ref: "12"
I dont exactly know the best way to get the object with $id "12". Based on the posts below it seems i should loop through the existing object, but i was hoping there was a jquery function that did that...
Many Thanks!
No, jQuery is not natively capable of resolving circular references in objects converted from JSON.
The only library for that which I know is Dojo's dojox.json.ref module.
But, your server application serializes that JSON somehow. Don't tell me that the solution it uses does not offer a deserialisation algorithm!
As my friend Alan, the author of the Xerox Courier (RPC over the net) library, used to say to me, "there are no pointers on the wire."
In other words, it is impossible for a JSON representation of a data structure to be circular. (But a circular structure can be flattened into a non-circular JSON structure.) As the JSON site says:
JSON is built on two structures:
A collection of name/value pairs. In various languages, this is realized as an object, record, struct, dictionary, hash table, keyed list, or associative array.
An ordered list of values. In most languages, this is realized as an array, vector, list, or sequence.
No pointers!
So the entire JSON will have been turned into Javascript Objects and/or Arrays after the jQuery parseJSON operation completes.
If the original stucture's ref_id values were used as the property names in the JSON / Javascript object, then they'll all be there.
The real issue is that you need to understand how your server serialized its data structure into the JSON data structure. Look in your server-side code to determine that.
Then use Javascript to de-serialize the JSON structure back into the best Javascript structure to fit your needs.
Re: Should i be iterating though the object and all its child objects until i find it, or is there an easier way?
The easier way would be to go through the Javascript structure once, and build up an additional "indexing" object whose properties are the #ref_id and the values are the original structure/value.
Sample:
var jsonCyclicReferenceFixed = JsonRecursive.parse(jsonWithRefAndId);
(function(){
function type(value){
var t = typeof(value);
if( t == "object" && value instanceof Array) {
return "array";
}
if( t == "object" && value && "$id" in value && "$values" in value) {
return "array";
}
return t;
}
function TypeConverterFactory(){
var converters = {};
var defaultConverter = {
fromJson: function(value){ return value; },
toJson: function(value){ return value; },
};
this.create = function(type){
var converter = converters[type];
if(!converter) return defaultConverter;
return converter;
};
this.register = function(type, converter){
converters[type] = converter;
converter.valueConverter = this.valueConverter;
};
}
function ObjectConverter(){
this.fromJson = function(obj){
if( obj == null ) return null;
if( "$ref" in obj ){
var reference = this.dictionary[obj.$ref];
return reference;
}
if("$id" in obj){
this.dictionary[obj.$id] = obj;
delete obj.$id;
}
for(var prop in obj){
obj[prop] = this.valueConverter.convertFromJson(obj[prop]);
}
return obj;
}
this.toJson = function(obj){
var id = 0;
if(~(id = this.dictionary.indexOf(obj))){
return { "$ref" : (id + 1).toString() };
}
var convertedObj = { "$id" : this.dictionary.push(obj).toString() };
for(var prop in obj){
convertedObj[prop] = this.valueConverter.convertToJson(obj[prop]);
}
return convertedObj;
}
}
function ArrayConverter(){
var self = this;
this.fromJson = function(arr){
if( arr == null ) return null;
if("$id" in arr){
var values = arr.$values.map(function(item){
return self.valueConverter.convertFromJson(item);
});
this.dictionary[arr.$id] = values;
delete arr.$id;
return values;
}
return arr;
}
this.toJson = function(arr){
var id = 0;
if(~(id = this.dictionary.indexOf(arr))){
return { "$ref" : (id + 1).toString() };
}
var convertedObj = { "$id" : this.dictionary.push(arr).toString() };
convertedObj.$values = arr.map(function(arrItem){
return self.valueConverter.convertToJson(arrItem);
});
return convertedObj;
}
}
function ValueConverter(){
this.typeConverterFactory = new TypeConverterFactory();
this.typeConverterFactory.valueConverter = this;
this.typeConverterFactory.register("array", new ArrayConverter);
this.typeConverterFactory.register("object", new ObjectConverter);
this.dictionary = {};
this.convertToJson = function(valor){
var converter = this.typeConverterFactory.create(type(valor));
converter.dictionary = this.dictionary;
return converter.toJson(valor);
}
this.convertFromJson = function(valor){
var converter = this.typeConverterFactory.create(type(valor));
converter.dictionary = this.dictionary;
return converter.fromJson(valor);
}
}
function JsonRecursive(){
this.valueConverter = new ValueConverter();
}
JsonRecursive.prototype.convert = function(obj){
this.valueConverter.dictionary = [];
var converted = this.valueConverter.convertToJson(obj);
return converted;
}
JsonRecursive.prototype.parse = function(string){
this.valueConverter.dictionary = {};
var referenced = JSON.parse(string);
return this.valueConverter.convertFromJson(referenced);
}
JsonRecursive.prototype.stringify = function(obj){
var converted = this.convert(obj);
var params = [].slice.call(arguments, 1);
return JSON.stringify.apply(JSON, [converted].concat(params));
}
if(window){
if( window.define ){
//to AMD (require.js)
window.define(function(){
return new JsonRecursive();
});
}else{
//basic exposition
window.jsonRecursive = new JsonRecursive();
}
return;
}
if(global){
// export to node.js
module.exports = new JsonRecursive();
}
}());
Sample:
// a object recursive
// var parent = {};
// var child = {};
// parent.child = child;
// child.parent = parent;
//
//results in this recursive json
var json = '{"$id":"0","name":"Parent","child":{"$id":"1","name":"Child","parent":{"$ref":"0"}}}'
//Parsing a Recursive Json to Object with references
var obj = jsonRecursive.parse(json);
// to see results try console.log( obj );
alert(obj.name);
alert(obj.child.name);

Serializing to JSON in jQuery [duplicate]

This question already has answers here:
Serializing an object to JSON
(4 answers)
Closed 5 years ago.
I need to serialize an object to JSON. I'm using jQuery. Is there a "standard" way to do this?
My specific situation: I have an array defined as shown below:
var countries = new Array();
countries[0] = 'ga';
countries[1] = 'cd';
...
and I need to turn this into a string to pass to $.ajax() like this:
$.ajax({
type: "POST",
url: "Concessions.aspx/GetConcessions",
data: "{'countries':['ga','cd']}",
...
JSON-js - JSON in JavaScript.
To convert an object to a string, use JSON.stringify:
var json_text = JSON.stringify(your_object, null, 2);
To convert a JSON string to object, use JSON.parse:
var your_object = JSON.parse(json_text);
It was recently recommended by John Resig:
...PLEASE start migrating
your JSON-using applications over to
Crockford's json2.js. It is fully
compatible with the ECMAScript 5
specification and gracefully degrades
if a native (faster!) implementation
exists.
In fact, I just landed a change in jQuery yesterday that utilizes the
JSON.parse method if it exists, now
that it has been completely specified.
I tend to trust what he says on JavaScript matters :)
All modern browsers (and many older ones which aren't ancient) support the JSON object natively. The current version of Crockford's JSON library will only define JSON.stringify and JSON.parse if they're not already defined, leaving any browser native implementation intact.
I've been using jquery-json for 6 months and it works great. It's very simple to use:
var myObj = {foo: "bar", "baz": "wockaflockafliz"};
$.toJSON(myObj);
// Result: {"foo":"bar","baz":"wockaflockafliz"}
Works on IE8+
No need for jQuery, use:
JSON.stringify(countries);
I haven't used it but you might want to try the jQuery plugin written by Mark Gibson
It adds the two functions: $.toJSON(value), $.parseJSON(json_str, [safe]).
No, the standard way to serialize to JSON is to use an existing JSON serialization library. If you don't wish to do this, then you're going to have to write your own serialization methods.
If you want guidance on how to do this, I'd suggest examining the source of some of the available libraries.
EDIT: I'm not going to come out and say that writing your own serliazation methods is bad, but you must consider that if it's important to your application to use well-formed JSON, then you have to weigh the overhead of "one more dependency" against the possibility that your custom methods may one day encounter a failure case that you hadn't anticipated. Whether that risk is acceptable is your call.
I did find this somewhere. Can't remember where though... probably on StackOverflow :)
$.fn.serializeObject = function(){
var o = {};
var a = this.serializeArray();
$.each(a, function() {
if (o[this.name]) {
if (!o[this.name].push) {
o[this.name] = [o[this.name]];
}
o[this.name].push(this.value || '');
} else {
o[this.name] = this.value || '';
}
});
return o;
};
If you don't want to use external libraries there is .toSource() native JavaScript method, but it's not perfectly cross-browser.
Yes, you should JSON.stringify and JSON.parse your Json_PostData before calling $.ajax:
$.ajax({
url: post_http_site,
type: "POST",
data: JSON.parse(JSON.stringify(Json_PostData)),
cache: false,
error: function (xhr, ajaxOptions, thrownError) {
alert(" write json item, Ajax error! " + xhr.status + " error =" + thrownError + " xhr.responseText = " + xhr.responseText );
},
success: function (data) {
alert("write json item, Ajax OK");
}
});
The best way is to include the polyfill for JSON object.
But if you insist create a method for serializing an object to JSON notation (valid values for JSON) inside the jQuery namespace, you can do something like this:
Implementation
// This is a reference to JSON.stringify and provides a polyfill for old browsers.
// stringify serializes an object, array or primitive value and return it as JSON.
jQuery.stringify = (function ($) {
var _PRIMITIVE, _OPEN, _CLOSE;
if (window.JSON && typeof JSON.stringify === "function")
return JSON.stringify;
_PRIMITIVE = /string|number|boolean|null/;
_OPEN = {
object: "{",
array: "["
};
_CLOSE = {
object: "}",
array: "]"
};
//actions to execute in each iteration
function action(key, value) {
var type = $.type(value),
prop = "";
//key is not an array index
if (typeof key !== "number") {
prop = '"' + key + '":';
}
if (type === "string") {
prop += '"' + value + '"';
} else if (_PRIMITIVE.test(type)) {
prop += value;
} else if (type === "array" || type === "object") {
prop += toJson(value, type);
} else return;
this.push(prop);
}
//iterates over an object or array
function each(obj, callback, thisArg) {
for (var key in obj) {
if (obj instanceof Array) key = +key;
callback.call(thisArg, key, obj[key]);
}
}
//generates the json
function toJson(obj, type) {
var items = [];
each(obj, action, items);
return _OPEN[type] + items.join(",") + _CLOSE[type];
}
//exported function that generates the json
return function stringify(obj) {
if (!arguments.length) return "";
var type = $.type(obj);
if (_PRIMITIVE.test(type))
return (obj === null ? type : obj.toString());
//obj is array or object
return toJson(obj, type);
}
}(jQuery));
Usage
var myObject = {
"0": null,
"total-items": 10,
"undefined-prop": void(0),
sorted: true,
images: ["bg-menu.png", "bg-body.jpg", [1, 2]],
position: { //nested object literal
"x": 40,
"y": 300,
offset: [{ top: 23 }]
},
onChange: function() { return !0 },
pattern: /^bg-.+\.(?:png|jpe?g)$/i
};
var json = jQuery.stringify(myObject);
console.log(json);
It's basically 2 step process:
First, you need to stringify like this:
var JSON_VAR = JSON.stringify(OBJECT_NAME, null, 2);
After that, you need to convert the string to Object:
var obj = JSON.parse(JSON_VAR);
One thing that the above solutions don't take into account is if you have an array of inputs but only one value was supplied.
For instance, if the back end expects an array of People, but in this particular case, you are just dealing with a single person. Then doing:
<input type="hidden" name="People" value="Joe" />
Then with the previous solutions, it would just map to something like:
{
"People" : "Joe"
}
But it should really map to
{
"People" : [ "Joe" ]
}
To fix that, the input should look like:
<input type="hidden" name="People[]" value="Joe" />
And you would use the following function (based off of other solutions, but extended a bit)
$.fn.serializeObject = function() {
var o = {};
var a = this.serializeArray();
$.each(a, function() {
if (this.name.substr(-2) == "[]"){
this.name = this.name.substr(0, this.name.length - 2);
o[this.name] = [];
}
if (o[this.name]) {
if (!o[this.name].push) {
o[this.name] = [o[this.name]];
}
o[this.name].push(this.value || '');
} else {
o[this.name] = this.value || '';
}
});
return o;
};

Categories

Resources