|
|
Comments and Discussions
|
|
 |

|
I noticed in fastBinary that you use const bytes instead of an enum for your token types. I wanted to see if going this route made any impact with my changes. The following are results from changing the myPropInfoType/Flags to const ints (.NET 4, AnyCPU on a 64bit machine, Release) . Diff here: http://pastebin.com/30faGq0u[^] (still includes my original changes)
const int:
e-dataset
fastjson serialize 71 53 54 53 53
fastjson deserialize 112 90 89 89 90
+dataset
fastjson serialize 327 338 333 327 325
fastjson deserialize 674 669 702 677 671
e-dataset
fastjson serialize 70 53 53 52 53
fastjson deserialize 113 90 89 90 89
+dataset
fastjson serialize 326 322 322 336 322
fastjson deserialize 675 700 669 673 670
e-dataset
fastjson serialize 73 53 57 58 52
fastjson deserialize 112 90 90 90 89
+dataset
fastjson serialize 321 320 321 318 322
fastjson deserialize 681 684 696 694 681
enum:
e-dataset
fastjson serialize 74 69 63 56 52
fastjson deserialize 138 103 91 108 90
+dataset
fastjson serialize 324 332 334 327 324
fastjson deserialize 677 682 675 688 675
e-dataset
fastjson serialize 73 53 56 52 53
fastjson deserialize 112 90 90 90 90
+dataset
fastjson serialize 327 324 320 319 323
fastjson deserialize 673 668 672 667 676
e-dataset
fastjson serialize 70 52 53 52 52
fastjson deserialize 111 89 90 89 91
+dataset
fastjson serialize 336 333 346 340 334
fastjson deserialize 678 675 685 683 674
There was no real consistent difference between the two. Which is good because I like enums. I would have got a little depressed if there was a performance hit in using them.
|
|
|
|

|
In fastBinaryJSON the TOKENS are used in the output so I can't change them to enum (performance hit in the conversion to output).
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.
|
|
|
|

|
... take a look at the binary version here : fastBinaryJSON[^]
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.
|
|
|
|

|
Ah yes, completely forgot about your BSON version . Will do. Have you thought about combining them under one repo, or having BSON be a subrepo, while having something like a fastJSON.Core for the shared code (along with making some use of InternalsVisableToAttribute)? Briefly scanning the code I saw the myPropInfo struct again, so I'm going to go out on a limb and assume that most of the reflection utilities are copy&pasted to BSON. If someone wanted to use both for whatever reason (eg, a game dev who develops with text but then ships using binary), they would end up with more memory overhead as both JSON and BSON libs would be duplicating that reflection code/data (at the very least).
Your Helper class in BSON seems to duplicate the GetBytes/ToXxx functions from BitConverter. I realize that you provide byte swapping functionality, but have you done speed comparisons to see if re-implementing those functions was faster than calling BitConverter's? Well, yours doesn't do any contract verification (bytes != null, etc) like BitConverter so that probably shaves off some cycles.
|
|
|
|

|
Well it's not BSON but a binary JSON, and yes most of the helper code is for performance.
As for combining the libraries, this is certainly desirable from my stand point in maintaining them both but the problem is the users of fastJSON are probably web devs and don't need binary, and the only people who need them both are network protocol and storage users which are few and trying to combine them will probably introduce extra layers and slow things down (speculating here).
I use them both in RaptorDB and there I factor out the same files and only use one.
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.
|
|
|
|

|
While going through your consoletest project, I noticed that you use DateTime for timing. Using Stopwatch is more precise in both timing and control over where you're timing. Eg (using bin_deserialize, line 211):
var stopwatch = new Stopwatch();
for (int pp = 0; pp < tcount; pp++)
{
BinaryFormatter bf = new BinaryFormatter();
MemoryStream ms = new MemoryStream();
colclass deserializedStore = null;
stopwatch.Restart();
bf.Serialize(ms, c);
for (int i = 0; i < count; i++)
{
stopwatch.Stop(); ms.Seek(0L, SeekOrigin.Begin);
stopwatch.Start();
deserializedStore = (colclass)bf.Deserialize(ms);
}
stopwatch.Stop();
Console.Write("\t" + stopwatch.ElapsedMilliseconds);
Just for being efficient in the test code itself, I created the stopwatch before the loop body (it's a reference type, not value like DateTime). From there, I start/restart (calling Restart is the same as calling Start on a fresh stopwatch) it after non-interesting operations (the MemoryStream ctor, etc) then essentially pause the stopwatch while Seek executes. Granted, it still means part of the for() loop itself is being timed, but overall it's a much better representation of your, or a 'rival's, API.
edit: Not sure if you noticed this (though you do have the bin_* methods commented out in Main) but none of the classes in dataobjects.cs are marked with [Serializable] so the bin_* methods will throw exceptions.
modified 14 Apr '13 - 12:54.
|
|
|
|

|
Please send me your full name so I can credit you in the next release.
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
Could you update your benchmarks to either benchmark against the latest version of Json.NET or remove Json.NET from them all together.
Thanks
James
|
|
|
|

|
Certainly, I will run the tests as soon as possible.
Thanks James!
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 have a class defined with an overloaded [] operator...for example:
public int this[int iX, int iY] { get { return m_aiData[iX,iY]; } set { m_aiData[iX,iY] = value;} }
However, the serializer seems to have a problem with this, giving me the exception "Common Language Runtime detected an invalid program."
I tested a variety of scenarios and this fails on *any* property of this type, unless of course I remove the "set", since it becomes read-only in that case and is ignored by fastJSON.
Is there any way around this? Is this something that can't be serialized? Of course I can make the property read-only and create a seperate function to "set" the values, but I'd really prefer not to, if possible. Thanks!
Edit: I forgot it doesn't handle n-dimension array, so I'll have to change some stuff anway But, I'd still like to have a definite answer.
modified 28 Mar '13 - 16:46.
|
|
|
|

|
While I can't speak for Mehdi, I'm fairly certain this is because fastJSON doesn't handle multi-dimensional arrays.
As a quick solution, you could try writing a simpler POCO that is used for storage only, and then translate to/from this new class before and after doing (de)serialization.
|
|
|
|

|
Unfortunately fastJSON does not handle multi-dimensianal arrays i.e. int[,].
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.
|
|
|
|

|
*edit* I got this to work using (Dictionary)Parse(json), but documentation doesn't seem to support that this is how it should be done. For now, I am satisfied, but there is room for improvement with ToObject()
Hi. I'm reposting my question from CodePlex as I realized it isn't a very popular forum to communicate to you.
I'm working on a localization project and would like to deserialize a json string to a Dictionary in which some of the values may be another Dictionary for size optimization purposes (essentially namespacing). An example of the json is below.
{
"app": {
"title": "TITLE_EN",
"desc": "DESC_EN",
"settings": {
"" : "SETTINGS_EN"
"title": "SETTINGS_TITLE_EN"
}
}
}
I plan to end up with something I can recurse through and flatten down into a less complex Dictionary.
Unfortunately, attempts at using fastJSON.JSON.Instance.ToObject>(json) results in an exception in mscorlib's Dictionary.cs. According to jsonlint.com the string is valid json.
I had success using Parse(json) and ToObject(json), but it insists upon nesting IList which is undesirable to me. Do you have any recommendations on how to achieve this with fastJSON? Thanks for your hard work on this project.
modified 21 Mar '13 - 14:30.
|
|
|
|

|
Is there a way to serialize a collection of unknown-type objects, and determine their original type after de-serialization?
EG: object[] toSerialize = new[]{ new Guid() };
If I serialize the above, the serialized form doesn't store the GUID's type, and the GUID is de-serialized into a string.
Is there a way around this? Do I have to use generics / Tuple to accomplish this?
|
|
|
|

|
Since json does not store type information and you only get strings and numbers, then no you can't.
fastJSON uses the type information from the class type you supply ($type property) for deserializtion.
You might want to look at my fastBinaryJSON project which overcomes this limitation.
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 hope you don't mind, but I created a fork of fastJSON:
https://github.com/kamranayub/fastJSON[^]
I added two features:
* RootElement support (it simply returns the first key match in the dictionary if present)
* Name variance (disabled by default)
I also organized the solution a bit because I had trouble getting everything running from your original source. I also pushed a Nuget package of my fork (different package name) so I could pull it into my project.
I separated the changes from the reorganization, so feel free to take a look at what I did. It would be great to see these updates in the core fastJSON! I just needed them right now.
|
|
|
|

|
Great job!
I might incorporate the property name variant override ( quite useful).
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.
|
|
|
|

|
One of the nice features of some other deserializers (RestSharp) is the ability to pass in a "root element" so you don't need to deserialize into a container class:
{
"person": {
"name": "Kamran"
}
}
fastJSON.JSON.Instance.ToObject<Person>(json, rootElement: "person")
This would be very helpful for REST APIs (or any service). Some APIs have useful containers (error, status, etc.) but the one I'm dealing with right now just adds a containing element for the heck of it.
-Kamran Ayub
|
|
|
|

|
Thanks!
It's probably faster to deserialize the entire json and extract the item you want in code:
var o = fastJSON.JSON.Instance.ToObject<objecttype>(json);
var p = o.Person;
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,
first: thanks for fixing the problem with the edge case with nulls.
Now I run into the problem, that through a REST request I receive a Json string which is varies, depending on the request. The object contains a property for an id, which can contain one or more ids
- In case with one id, the property: is like "id": 123.
- In case of multiple ids, the property is: "id": "1234,12546,52344"
The problem is now: if only one id is passed (id=12) the parser throughs a cast error. The reason is, that fastJson uses a direct cast to convert the received object. Yet in the case of multiple values, the case is successful.
My question is now: why are you using a direct cast and not a ToString() method? With the ToString() method I can cover both scenarios.
Thanks for your input.
Chris
|
|
|
|

|
If id is a string then you shouldn't have a problem, but if it is an int then you can't put "1234,12345" in 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.
|
|
|
|

|
Would it be possible to update the version submitted to NuGet? It's 1.9.6 at the moment and you have fixed a number of bugs between then and now.
Kind thanks,
Roja
|
|
|
|

|
Concerning objects implementing IList or ICollection, all properties (other than items) are not serialized.
This snippet of serializer's code, seems to confirm this fact :
else if (obj is Array || obj is IList || obj is ICollection)
WriteArray((IEnumerable)obj);
Is it a normal behaviour ?
|
|
|
|

|
I will look into this for the next release.
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 Mehdi for the quick response.
I have made the changes, it made the code simpler.
|
|
|
|

|
Also, don't neglect SortedList.
ATM it doesn't handle those too well.
Serialization mapping is partial and Deserialization throws exception for unknown type.
Also, given that both key-type and value-type of collection items could be object, the only way you could make deserialization work all the time is by inserting their [full type name] into the JSON string.
You can try all you want, but you're not gonna dodge this one and have a fail-safe product.
g
modified 10 Feb '13 - 1:44.
|
|
|
|

|
the only way you could make deserialization work all the time is by inserting their [full type name] into the JSON string
Not so sure, since deserialization can be done with a "target type" which have the needed full descriptor.
However, the embedded objects within fields/properties of the "target type" could be deserialized only according to the type of those fields/properties. So, if you put in a field/property of "object" type, an instance of a "xxx" type, deserializer have no way to guess the "xxx" type.
|
|
|
|

|
Hi,
I have a test-case which success to serialize, but fail to deserialize.
Here some code:
Class definitions:
[Serializable]
public class ConfigFormData
{
public Point Location { get; set; }
public Size Size { get; set; }
}
[Serializable]
public class ConfigData
{
public Dictionary<string, ConfigFormData> Forms { get; set; }
}
Usage:
ConfigData data = new ConfigData();
data.Forms = new Dictionary<string, ConfigFormData>();
data.Forms.Add(Name, new ConfigFormData(){Location = Location, Size = Size});
string json = fastJSON.JSON.Instance.ToJSON(data);
ConfigData data2;
data2 = fastJSON.JSON.Instance.ToObject<ConfigData>(json);
Json string:
{
"$types" : {
"WindowsFormsApplication2.Form1+ConfigData, WindowsFormsApplication2, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" : "1",
"WindowsFormsApplication2.Form1+ConfigFormData, WindowsFormsApplication2, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" : "2",
"System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" : "3",
"System.Drawing.Size, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" : "4"
},
"$type" : "1",
"Forms" : {
"Form1" : {
"$type" : "2",
"Location" : {
"$type" : "3",
"X" : 147,
"Y" : 147
},
"Size" : {
"$type" : "4",
"Width" : 384,
"Height" : 356
}
}
}
}
And the exception (in french, sorry):
Message: L'objet doit implémenter IConvertible.
Stack:
à System.Convert.ChangeType(Object value, Type conversionType, IFormatProvider provider)
à fastJSON.JSON.ChangeType(Object value, Type conversionType)
à fastJSON.JSON.ParseDictionary(Dictionary`2 d, Dictionary`2 globaltypes, Type type, Object input)
à fastJSON.JSON.CreateStringKeyDictionary(Dictionary`2 reader, Type pt, Type[] types, Dictionary`2 globalTypes)
à fastJSON.JSON.ParseDictionary(Dictionary`2 d, Dictionary`2 globaltypes, Type type, Object input)
à fastJSON.JSON.ToObject(String json, Type type)
à fastJSON.JSON.ToObject[T](String json)
à WindowsFormsApplication2.Form1.button1_Click(Object sender, EventArgs e) dans D:\tmp\WindowsFormsApplication2\Form1.cs:ligne 46
|
|
|
|

|
This should have been fixed in the current version, I will check again.
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.
|
|
|
|

|
Hi, better later than never
I've check with the last version of FastJSON (2.0.13) and I still have the same exception. (same test case)
Sorry!
|
|
|
|

|
Point and Size (and other GDI types etc.) require the CustomType to be enabled as they are not supported by fastJSON ( you have to write de/serializers for them yourself).
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,
I'm very impressed with your implementation here. Particularly your performance results - the results against BinaryFormatter are very telling - and the fact that you beat Stack. I prototyped my own binary serializer a few years ago (never went into production), that was around 40x faster than the binary serializer, so I can appreciate a text-based format beating the binary formatter.
I actually needed fastJSON for it's ability to deserialize the more complex OO types. I can't believe that Stack resisted your requests. Although it would be good to call your solution a JSON and JSONOO serializer, for clarity.
Also, I have thoughts of re-visiting my binary formatter, now called eXtensible Binary eXchange (XBX). I particularly want to use it with Javascript over WebSockets. I would build it open source, and it would be tunable and configurable, with default setup for fulfilling most applications, but able to be tuned to minimize payload and maximize performance.
Please contact me if you would like more details and would like to help. I can share my draft Google Doc and we could work on the specification first, and possibly co-author another codeproject article.
|
|
|
|

|
Hello everyone, I can not do with json decode, please help?
string jsonText = "[[{\"language\":\"es\",\"isReliable\":false,\"confidence\":0.4517133956386293},{\"language\":\"pt\",\"isReliable\":false,\"confidence\":0.08356545961002786}],[{\"language\":\"en\",\"isReliable\":false,\"confidence\":0.17017828200972449},{\"language\":\"vi\",\"isReliable\":false,\"confidence\":0.13673655423883319}]]}}";
var newobj = fastJSON.JSON.Instance.ToObject<List<SubFolder>>(jsonText);
private class SubFolder
{
public string language { get; set; }
public string isReliable { get; set; }
public string confidence { get; set; }
}
> the array would be this:
{"data":{"detections":[[{"language":"es","isReliable":false,"confidence" .4517133956386293},{"language":"pt","isReliable":false,"confidence" .08356545961002786}],[{"language":"en","isReliable":false,"confidence" .17017828200972449},{"language":"vi","isReliable":false,"confidence" .13673655423883319}]]}}
|
|
|
|

|
First a List<SubFolder> becomes [{"language":null,"isReliable":null,"confidence":null},{"language":null,"isReliable":null,"confidence":null}]
Note the single square bracket, so your json string is not correct.
Second the types must be public and not private for fastJSON to work.
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.
|
|
|
|

|
Im happy with this lib first of all,
but I recently found a bug
you can cast an int[][] from the json string "[[0,0,2]]"
Greetings
|
|
|
|

|
Do you have some sample code for this?
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 will throw an exception that it can't cast an int[][] from an int[]
fastJSON.JSON.Instance.ToObject<int[][]>>("[[0,0,2]]");
|
|
|
|

|
Hello, Just wanted to ask, if there are any plans of making fastJSON available to WinRT platform? Regards, Dovydas
|
|
|
|

|
Thanks Dovydas!
Currently I don't have the resources for WinRT testing, judging by the Silverlight debacle WinRT will probably not work, I don't know.
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.
|
|
|
|

|
Change fastJSON version from 1.9.6 to current version 2.0.13 and now I cannot longer deserialize classes with enum properties. Always get exception "InvalidCastException: Cannot convert type System.Int64 to type System.String".
Compiling fastJSON for .NET 2.0
Any ideas?
Best regards,
Markus
|
|
|
|

|
Thanks Mark!
Can you give me a sample code that you have problems 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.
|
|
|
|

|
If jp.UseOptimizedDatasetSchema is set with false and the json text with dataset is handled by the method "Beautify", the dataset's xml schema in the json text will be not well-formed. I guess that the method of "Formatter.PrettyPrint" is not implemented correctly.
|
|
|
|

|
Modification 1: // StringBuilder replaced with string public static bool IsEscaped(string sb, int index) { bool escaped = false; while (index > 0 && sb[--index] == '\\') escaped = !escaped; return escaped; } Modification 2: case '"': case '\'': output.Append(ch); if (!IsEscaped(input, i)) // not using output // The length of output is unexpected.
|
|
|
|

|
Thanks! I will look into it and post 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.
|
|
|
|

|
I had this bug too and the modifications helped.
|
|
|
|

|
A bug !!! All objects must be declared with "public", otherwise, the exception - failed to fast create instance - will be threw during deserialization from JSON text.
|
|
|
|

|
In the words of Huey Lewis : "that's the way it is".
Generally serializers work with public classes, properties and fields, and fastJSON is no exception.
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 having problems using fastJSON in my Silverlight 4 application.
When I call: fastJSON.JSON.Instance.ToJSON(myObject);
I get an exception here:
DynamicMethod getter = new DynamicMethod("_", typeof(object), new Type[] { typeof(object) }, type);
Exception:
Attempt by security transparent method 'fastJSON.Reflection.CreateGetMethod(System.Type, System.Reflection.PropertyInfo)' to access security critical method 'System.Reflection.Emit.DynamicMethod..ctor(System.String, System.Type, System.Type[], System.Type)' failed.
Do you have any idea how I could get this fixed?
I took the fastJSON-SL project and builded. Then added the .dll to my SL app.
Best Regards
Frederik
|
|
|
|

|
Right click on your application and make sure the Silverlight version is 4 and not 5.
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.
|
|
|
|

|
Can you compare performance with
|
|
|
|
 |
|
|
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,555,131 |
| Downloads | 25,745 |
| Bookmarked | 462 times |
|
|