|
|
Comments and Discussions
|
|
 |

|
First of all, thanks for sharing that little useful library! I just wonder why doesn't it support deserialization of arrays (admittedly, you can use List, but still)? The necessary code changes seem to be trivial.
Regards,
Andrew
|
|
|
|

|
Thanks Andrew!
The following works fine:
public class arrayclass
{
public int[] ints { get; set; }
public string[] strs;
}
[Test]
public static void ArrayTest()
{
arrayclass a = new arrayclass();
a.ints = new int[] { 3, 1, 4 };
a.strs = new string[] {"a","b","c"};
var s = fastJSON.JSON.Instance.ToJSON(a);
var o = fastJSON.JSON.Instance.ToObject(s);
}
I have added it to the unit tests.
Its the man, not the machine - Chuck Yeager
If at first you don't succeed... get a better publicist
If the final destination is death, then we should enjoy every second of the journey.
|
|
|
|
|

|
Good tips
|
|
|
|

|
¿It is possible to deserialize immutable classes?
If i have a class like this:
class Immutable
{
public Immutable( long id )
{
this.Id = id;
}
public long Id { get; private set; }
}
with JsonNet i must add a attribute to them and an empty constructor and leave the class like this:
class Immutable
{
[JsonConstructor]
private Immutable() : this(0) { }
public Immutable( long id )
{
this.Id = id;
}
[JsonProperty]
public long Id { get; private set; }
}
Thanks
Iker eL_FRuTeRo
|
|
|
|

|
You don't need any attributes with fastJSON, but a default constructor is required.
You can get the json output for readonly properties by setting the ShowReadOnlyProperties = true in JSONParameters.
Obviously when deserializing the readonly properties will be ignored and not set.
Its the man, not the machine - Chuck Yeager
If at first you don't succeed... get a better publicist
If the final destination is death, then we should enjoy every second of the journey.
|
|
|
|

|
In a immutable object, all its properties are readonly as they are immutable.
can i deserialie them without adding a public setter?
Thank you very much
Iker eL_FRuTeRo
|
|
|
|

|
Unfortunately not since the deserializer is using the Set method defined on the class and if it is private then it will fail.
Obviously the designer of the class made the decision to make properties private, so it is unsafe to assume anything about the internal structure of the class when reflecting at the level of fastJSON.
Its the man, not the machine - Chuck Yeager
If at first you don't succeed... get a better publicist
If the final destination is death, then we should enjoy every second of the journey.
|
|
|
|

|
I am trying to serialize and deserialize a variable of type System.Type. Is that possible? If yes, what am I doing wrong?
System.Type type = typeof(string);
var jsonText = JSON.Instance.ToJSON(type);
var newType = JSON.Instance.ToObject(jsonText) as Type;
I get the following exception:
System.Exception : Failed to fast create instance for type 'System.RuntimeType' from assemebly 'System.RuntimeType, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'
----> System.ArgumentNullException : Value cannot be null.
Parameter name: con
at fastJSON.JSON.FastCreateInstance(Type objtype) in JSON.cs: line 164
at fastJSON.JSON.ParseDictionary(Dictionary`2 d, Dictionary`2 globaltypes, Type type) in JSON.cs: line 471
at fastJSON.JSON.ToObject(String json, Type type) in JSON.cs: line 82
at fastJSON.JSON.ToObject(String json) in JSON.cs: line 75
(I also posted this on CodePlex: [^]. I am not sure where the official forum is.)
|
|
|
|

|
Serializers are generally meant to process "data" types not "meta" types, so unfortunately you can't work with Type as an input.
I prefer this forum than Codeplex as provides a better interface and is easier to work with.
Its the man, not the machine - Chuck Yeager
If at first you don't succeed... get a better publicist
If the final destination is death, then we should enjoy every second of the journey.
|
|
|
|

|
Trying to convert several legacy MVC3 apps to use fastJSON serializer to replace heavy Newtonsoft.Json.JsonConvert.SerializeXmlNode on XMLdocument or Datasets. Our client JavaScript apps require the Ex1 format below for use in jqGrid library. Tried w/ fastJSON (Ex4 & Ex5 output) but can not seem to get the key:value format like Ex1. Is Ex1 serialized output format possible in fastJSON? How? Many thanks for your help!
---------------------------------------------------------------------------
Ex1:Newtonsoft.Json.JsonConvert.SerializeXmlNode
{"person":[{"@id":"1","name":"Alan","url":"http://www.google.com"},{"@id":"2","name":"Louis","url":"http://www.yahoo.com"}]}
---------------------------------------------------------------------------
Ex2:JavaScriptSerializer.Serialize(xmlDoc.InnerXml)
"\u003croot\u003e\u003cperson id=\"1\"\u003e\u003cname\u003eAlan\u003c/name\u003e\u003curl\u003ehttp://www.google.com\u003c/url\u003e\u003c/person\u003e\u003cperson id=\"2\"\u003e\u003cname\u003eLouis\u003c/name\u003e\u003curl\u003ehttp://www.yahoo.com\u003c/url\u003e\u003c/person\u003e\u003c/root\u003e"
---------------------------------------------------------------------------
Ex3:JavaScriptSerializer: DataSetToJSON using dictionary
{"person":[["Alan","http://www.google.com","1"],["Louis","http://www.yahoo.com","2"],null]}
---------------------------------------------------------------------------
Ex4:fastJSON: DataSet to dictionary
{"person":[["Alan","http://www.google.com","1"],["Louis","http://www.yahoo.com","2"],null]}
---------------------------------------------------------------------------
Ex5:fastJSON.JSON.Instance.ToJSON(ds)
{"$schema":{"$type":"fastJSON.DatasetSchema, fastJSON, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null","Info":["person","name","System.String","person","url","System.String","person","id","System.String"],"Name":"root"},"person":[["Alan","http://www.google.com","1"],["Louis","http://www.yahoo.com","2"]]}
---------------------------------------------------------------------------
|
|
|
|

|
As far as I can see you need
{"property": [ {row in object style key:value with a @id row counter}, {next row} ] }
Which outputs the column names also, while fastJSON outputs in the following style to save space:
{"property": [ [row data only], [next row] ] }
Currently fastJSON does not do this, however you can write your own custom serializer delegate for the property type your need.
Its the man, not the machine - Chuck Yeager
If at first you don't succeed... get a better publicist
If the final destination is death, then we should enjoy every second of the journey.
|
|
|
|

|
Hi,
what do you think about to add generic overload(s) of RegisterCustomType method?
something like your overload public T ToObject<T>(string json) for public object ToObject(string json)
I suggest
public void RegisterCustomType<T>(Func<T, string> serializer, Func<string, T> deserializer)
{
RegisterCustomType(typeof(T), (o) => serializer((T)o), (s) => deserializer(s));
}
and/or or (implements both overloads is not a good idea, this cause an ambiguous call when you call method using Lambda Expression)
public void RegisterCustomType<T>(Serialize<T> serializer, Deserialize<T> deserializer)
{
RegisterCustomType(typeof(T), (o) => serializer((T)o), (s) => deserializer(s));
}
adding delegate fields
public delegate string Serialize<T>(T data);
public delegate T Deserialize<T>(string data);
Thank you for sharing your great job
Francesco
modified 19-Sep-12 5:01am.
|
|
|
|

|
Nice, Francesco!
Will do in the next release soon.
Its the man, not the machine - Chuck Yeager
If at first you don't succeed... get a better publicist
If the final destination is death, then we should enjoy every second of the journey.
|
|
|
|
|
|

|
Hi Mehdi,
under features you list fastJson as being threadsafe. I wonder if the _usingglobals field doesn't break this.
Unless you specify either true or false globally and never change it
through the Parameters, you can end up with the following scenario:
E.g. _usingglobals is set to false per Parameters.
Deserializing a json string which was serialized with global types and extensions will set it to true in ParseDictionary.
Intermittent serialization on another thread sets it back to false.
Ths initial Deserialization hits the "if (found)" on a sub-object (or even on the initial object after a thread yield), tn contains a number (e.g. "2") but _usingglobals is false again.
Therefore it will *not* look up the globaltypes but instead ultimately call Type.GetType("2") which must fail.
Cheers
Phil
|
|
|
|

|
Global type processing is handled in a class which is created per serialize/deserialize call, so it will not conflict.
Anyway it is being used aggressivly in RaptorDB which is testing it to it's metal.
If you do find any problem in the field let me know and I will fix it.
Its the man, not the machine - Chuck Yeager
If at first you don't succeed... get a better publicist
If the final destination is death, then we should enjoy every second of the journey.
|
|
|
|
|

|
This is intriguing...
I used the MS singelton pattern, I will change the code and see how it performs.
Thanks Phil!
Its the man, not the machine - Chuck Yeager
If at first you don't succeed... get a better publicist
If the final destination is death, then we should enjoy every second of the journey.
|
|
|
|

|
Just to be sure: if you use the same kind of fix, you will need to make Parameters static + threadsafe, too. If you like, you can have a look at my fastJson fork on github. I essentially introduced a new static GlobalParameters and changed the Parameters to be an instance property accessing the new static one, for backwards compatbility.
It's funny that this went unnoticed (since 2.0.0 I guess). Probably the combination of sometimes using extensions and sometimes not is not too common.
Anyway, thank you for a really great library
|
|
|
|

|
Your right, it has always bugged me, but most people (me included) just use the defaults all the way and don't change mid execution.
ThreadStatic is very cool as I looked it up, learned something today, thanks.
Its the man, not the machine - Chuck Yeager
If at first you don't succeed... get a better publicist
If the final destination is death, then we should enjoy every second of the journey.
|
|
|
|

|
Mehdi,
I found this discussion because occasionally I am getting an error when using fastJSON (2.0.12) in a WPF app, which uses separate threads to update the UI. It is getting a null ref exception on globaltypes.TryGetValue in the following code block of ParseDictionary because globaltypes is null:
if (_usingglobals)
{
object tname = "";
if (globaltypes.TryGetValue((string)tn, out tname))
tn = tname;
}
The state of globaltypes and _usingglobals are out of sync, which seems to be the issue discussed in this thread. I'm just guessing that _usingglobals is getting set to true somewhere else incorrectly.
I notice that elsewhere in this thread, Philip Jander made the statement "if you use the same kind of fix, you will need to make Parameters static + threadsafe, too", but this does not appear to have been implemented in version 2.0.6 along with the other threading fixes. _usingglobals is part of Parameters. Do you think this might be the cause of this issue?
Thanks,
Jeff Montgomery
|
|
|
|

|
Thanks Jeff!
This seems to be an edge case, I will try to track it down it would help if you can give me a test case where this happens for you.
Its the man, not the machine - Chuck Yeager
If at first you don't succeed... get a better publicist
If the final destination is death, then we should enjoy every second of the journey.
|
|
|
|

|
As a sidenote (unrelated), the JSON generated for "ConcurrencyClassB" in the test has an extra comma. It doesn't seem to hurt, but I guess it shouldn't be there:
{,"PayloadB":{}}
|
|
|
|

|
Thanks I will check this, probably an edge case in the before after stringbuilders.
Its the man, not the machine - Chuck Yeager
If at first you don't succeed... get a better publicist
If the final destination is death, then we should enjoy every second of the journey.
|
|
|
|

|
From a fast look, it seems that the culprit is
if (i == 0) _output.Append(",");
in JsonSerializer.
I let this comma pass, only if g.Count was > 1 in the first place *or* $type was written. It seems that this fixes the problem.
Cheers
Phil
|
|
|
|

|
Commas should *finally* be fixed in v2.0.13.
Its the man, not the machine - Chuck Yeager
If at first you don't succeed... get a better publicist
If the final destination is death, then we should enjoy every second of the journey.
|
|
|
|

|
Hi @ all,
i'm a beginner in C# but i have good knowledge of PHP & Phyton.
I have a Program which opens a JSON encoded file and modifies it with File.Append() but i want to edit the JSON as an Array (or something similar), so i can search specific keys and edit the values.
i can load the file:
object jsonText;
file_path = "path_to_file"
jsonText = fastJSON.JsonParser.JsonDecode(File.ReadAllText(file_path));
How can i loop through the key0>values or edit specific values ?
|
|
|
|

|
Use Parse() it will give you dictionaries and lists.
Its the man, not the machine - Chuck Yeager
If at first you don't succeed... get a better publicist
If the final destination is death, then we should enjoy every second of the journey.
|
|
|
|

|
Thank you very much for your help!
My Code Now:
object jsonText;
temp = File.ReadAllText(path);
jsonText = fastJSON.JSON.Instance.Parse(temp);
i get the JSON in jsonText but i find no way to loop through the array or to modify explicit key=>value pairs :/
Can you give me a helping line what i do wrong?
modified 17-Sep-12 8:02am.
|
|
|
|

|
Sorry can you help me? i don't get it.
if i use this, i get the Object but i cant loop through it:
object jsonText;
jsonText = fastJSON.JSON.Instance.Parse(temp);
if i cast it as a Dictonary, jsonText is NULL:
Dictionary<string, string> jsonText;
jsonText = fastJSON.JSON.Instance.Parse(temp) as Dictionary<string, string>;
|
|
|
|

|
It should be Dictionary<string,object> if the original object was a class otherwise it could be List<object> if it was an array.
Any way use
var o = fastJSON.JSON.Instance.Parse(temp);
and run in the debugger and you will see the structure if you watch the o variable.
Its the man, not the machine - Chuck Yeager
If at first you don't succeed... get a better publicist
If the final destination is death, then we should enjoy every second of the journey.
|
|
|
|

|
Looks good ... I don't have VS2010 ... but out of curiosity can it handle the following case:
Class Animal
-> Zoo BelongsToZoo
-> String AnimalName
Class Zoo
-> String ZooName
-> list Animals
In the above case if we have an animal with the zoo set to something, and the zoo object contains the same animal in its list xml serialization will not work, does yours?
Kris
modified 8-Sep-12 2:01am.
|
|
|
|

|
Yes and no, there is a 10 [configurable] levels deep limit that the serializer will go down a nested recursive hierarchy before breaking out of the loop.
Flat "text" serialize formats like XML and JSON are not meant to be used with graph memory structures.
It is possible to create a structure of list of objects and graph which use pointers to the object list which could work (much like how $types are handled).
Interesting concept...
Its the man, not the machine - Chuck Yeager
If at first you don't succeed... get a better publicist
If the final destination is death, then we should enjoy every second of the journey.
|
|
|
|

|
Hrm... so your serializer would serialize each level of the same animal as a separate object?
In that case... when the object gets originally created:
giraffe.BelongsToZoo.animals.contains(giraffe)
would equal true...
but when serialized and deserialized this would not be the case as the giraffe in the zoo would be a different object.
The binary serializer does not have this issue.
Kris
modified 8-Sep-12 2:01am.
|
|
|
|

|
Yes that is the case, like I said "text" serializers have this problem.
Its the man, not the machine - Chuck Yeager
If at first you don't succeed... get a better publicist
If the final destination is death, then we should enjoy every second of the journey.
|
|
|
|

|
Couldn't a text serializer go ...
Each time you serialize an object add it to a list
if the object that we are serializing has already been serialised (in the list) then add a pointer to the location that it was serialized instead of trying to re-serialize it.
... then it should then be able to correctly text serialize cyclic objects?
Also it isn't a limitation of text serializers ... some work with cyclic objects using the method that i discussed above
Kris
|
|
|
|

|
I did say this in my original answer.
Its the man, not the machine - Chuck Yeager
If at first you don't succeed... get a better publicist
If the final destination is death, then we should enjoy every second of the journey.
|
|
|
|

|
whops :P didn't see that
... out of curiosity why is it limited to 10 levels deep?
Kris
|
|
|
|

|
10 is arbitrary, the limit is so you don't go in an endless loop.
Its the man, not the machine - Chuck Yeager
If at first you don't succeed... get a better publicist
If the final destination is death, then we should enjoy every second of the journey.
|
|
|
|
|

|
Hello Mr Gholam,
at first... i'm using fastJSON a lot and it is now my standard for serializing/deserializing and storing any sort of data. It is so great, thanks for all that great work!
Now to the (little) problem. If i have a object, which is null (see code below) and want to serialize that, i get an exception.
This is for many people okay, but wouldn't it be better, just to check if the object is null and then to return "null"? Because in my application, it is allowed, that for example that property is null. But that would crash my serialization.
Dictionary<string,string> myDict = null;
fastJSON.JSON.Instance.ToJSON(myDict);
Maybe we could do this with a new JSONParameter?
Is there any way to get this as "standard" in your project? I wouldn't like now to create my own branch, just for this simple piece of code, which would improve a lot of scenarios for all developers out there.
Thank you!
|
|
|
|

|
You would expect "null" as an output (without the quotes).
I will fix this in the next release thanks.
Its the man, not the machine - Chuck Yeager
If at first you don't succeed... get a better publicist
If the final destination is death, then we should enjoy every second of the journey.
|
|
|
|

|
This would be great. Thank you very much.
|
|
|
|

|
JSONParameters JSONP = new JSONParameters();
JSONP.UseExtensions = false; JSONP.SerializeNullValues = false;
JSONP.ShowReadOnlyProperties = true;
Response.ContentType = "text/plain";
Response.Write(JSON.Instance.ToJSON(new testcl(), JSONP));
class testcl{
public int cardType;
public bool groupStatus;
public string groupQBId;
}
"cardType":0,"groupStatus":false}
fix:
internal string ConvertToJSON(object obj)
{
WriteValue(obj);
string str = "";
if (_params.UsingGlobalTypes && _globalTypes != null && _globalTypes.Count > 0)
{
StringBuilder sb = _before;
sb.Append("\"$types\":{");
bool pendingSeparator = false;
foreach (var kv in _globalTypes)
{
if (pendingSeparator) sb.Append(',');
pendingSeparator = true;
sb.Append("\"");
sb.Append(kv.Key);
sb.Append("\":\"");
sb.Append(kv.Value);
sb.Append("\"");
}
sb.Append("},");
sb.Append(_output.ToString());
str = sb.ToString();
}
else
str = _before.ToString() + _output.ToString();
return str;
}
|
|
|
|

|
the error occurs under the condition:
a) UseExtensions = false
b) UsingGlobalTypes = true (which is default)
and (_globalTypes.Count == 0)
therefore fix it this way (see writeObject, where _before is created, and _output is cleared:
if (_params.UsingGlobalTypes)
{
StringBuilder sb = _before; if (_globalTypes != null && _globalTypes.Count > 0)
{
sb.Append("\"$types\":{");
...
}
sb.Append(_output.ToString());
str = sb.ToString();
}
else
str = _output.ToString();
return str;
|
|
|
|

|
Thanks, I will add the code in the next release soon.
Its the man, not the machine - Chuck Yeager
If at first you don't succeed... get a better publicist
If the final destination is death, then we should enjoy every second of the journey.
|
|
|
|

|
bug ex:
{
"cardType":"CUSTOMCODE",
"groupStatus":false,
},
fix code:
foreach (var p in g)
{
object o = p.Getter(obj);
if ((o == null || o is DBNull) && _params.SerializeNullValues == false)
continue;
else
{
if (append)
_output.Append(',');
WritePair(p.Name, o);
if (o != null && _params.UseExtensions)
{
Type tt = o.GetType();
if (tt == typeof(System.Object))
map.Add(p.Name, tt.ToString());
}
append = true;
}
}
|
|
|
|

|
Please send me the code that generated this (the object you were serializing).
Its the man, not the machine - Chuck Yeager
If at first you don't succeed... get a better publicist
If the final destination is death, then we should enjoy every second of the journey.
|
|
|
|
 |
|
|
General News Suggestion Question Bug Answer Joke Rant Admin
|
Smallest, fastest polymorphic JSON serializer (with Silverlight4 and MonoDroid support)
| Type | Article |
| Licence | CPOL |
| First Posted | 19 Feb 2011 |
| Views | 1,599,269 |
| Downloads | 26,640 |
| Bookmarked | 467 times |
|
|