What libraries are available to handle JSON in .Net? I've seen this: http://james.newtonking.com/projects/json-net.aspx but would prefer a native library, if possible.
I have been using the JavaScriptSerializer some to expose data structures from a WCF service to Ajax calls, and it has been working out quite well.
The JavaScriptSerializer has been marked as obsolete in .NET 3.5 and but you could use the DataContractJsonSerializer.
EDIT: See this question on SO about whether JavaScriptSerializer is actually obsolete going forward in the .NET BCL. It looks like JavaScriptSerializer is no longer obsolete in .NET 3.5 SP1 - so it's probably fine to use that. If in doubt, you can use the contract serializer from WCF, or JSON.NET (if you're willing to include 3rd party code).
Here's some wrapper code to make using DataContractJsonSerializer nicer.
using System.Runtime.Serialization;
using System.Runtime.Serialization.Json;
public class JSONHelper
{
public static string Serialize<T>(T obj)
{
DataContractJsonSerializer serializer =
new DataContractJsonSerializer(obj.GetType());
using( MemoryStream ms = new MemoryStream() )
{
serializer.WriteObject(ms, obj);
string retVal = Encoding.Default.GetString(ms.ToArray());
return retVal;
}
}
public static T Deserialize<T>(string json)
{
using( MemoryStream ms = new MemoryStream(Encoding.Unicode.GetBytes(json)) )
{
DataContractJsonSerializer serializer =
new DataContractJsonSerializer(typeof(T));
T obj = (T)serializer.ReadObject(ms);
ms.Close();
return obj;
}
}
}
The code above is courtesy of: http://pietschsoft.com/post/2008/02/NET-35-JSON-Serialization-using-the-DataContractJsonSerializer.aspx,
I have altered it from it's original form to use best practices for object disposal (the using pattern .NET supports).
If you can require .Net 3.5, use System.Web.Script.Serialization.JavaScriptSerializer
Related
Is there any json serializer library that work in .netcore and .Net3.5?
I need to use a library in a multiplatform project the problem is that Newtonsoft's library works only in .Net Framework and System.Text.Json only works in .netcore.
** I tried Json.Net but no luck. I get this kind of error on all of the libraries:
You can use DataContractJsonSerializer
I am using it in my .net standard library to serialize and de-serialize my model objects to json.
public static string PrepareJsonString<T>(object objectToBeParsed)
{
DataContractJsonSerializer dataContractSerializer = new DataContractJsonSerializer(typeof(T));
string json = string.Empty;
using (var ms = new MemoryStream())
{
dataContractSerializer.WriteObject(ms, (T)objectToBeParsed);
ms.Position = 0;
StreamReader sr = new StreamReader(ms);
json = sr.ReadToEnd();
}
return json;
}
public static object PrepareObjectFromString<T>(string json)
{
DataContractJsonSerializer dataContractSerializer = new DataContractJsonSerializer(typeof(T));
using (var memoryStream = new MemoryStream(Encoding.UTF8.GetBytes(json)))
{
var deSerializedUser = dataContractSerializer.ReadObject(memoryStream);
return deSerializedUser;
}
}
sample to consume this functions
List<MyModel> list= PrepareObjectFromString<List<MyModel>>(myJson);
or
MyModel list= PrepareObjectFromString<MyModel>(myJson);
string json=PrepareJsonString<MyModel>(myModelInstance);
Hope this helps.
Thank you.
I have a protobuf object that I am sending from a C# application (using clrZmq) to a C++ service (using the zmq C++ bindings) on a local machine (for testing). I attempt to send my object from C# using the following
Taurus.Odds odds = Util.GetFakeOdds();
using (var context = ZmqContext.Create())
using (var socket = context.CreateSocket(SocketType.REQ))
{
byte[] buffer = null;
socket.Connect(TARGET); // TARGET = "tcp://127.0.0.1:6500"
Taurus.FeedMux mux = new Taurus.FeedMux();
mux.type = Taurus.FeedMux.Type.ODDS;
mux.odds = odds;
SendStatus status = socket.Send(mux.ToByteArray());
if (status == SendStatus.Sent)
{
int i;
byte[] arr = socket.Receive(buffer, SocketFlags.None, out i);
Taurus.Bet bet = buffer.ToObject<Taurus.Bet>();
}
...
}
Where I am serializing to my Taurus.Odds object to byte[] via the extension method
public static byte[] ToByteArray(this object o)
{
if(o == null)
return null;
BinaryFormatter bf = new BinaryFormatter();
using (MemoryStream ms = new MemoryStream())
{
bf.Serialize(ms, o);
return ms.ToArray();
}
}
I see in my C++ application that the code receives the message, but the C++ ZMQ classes fail to de-serialize it correctly. I have some Java code that send to the C++ code in the same way without issue. My question is, am I sending my object via ZMQ correctly in the above and if not what am I doing wrong?
Thanks for your time.
Here's your error:
I am serializing to my Taurus.Odds object to byte[] via the extension method
...
BinaryFormatter bf = new BinaryFormatter();
...
You seem to be unaware of what BinaryFormatter is. It is in no way related to ProtoBuf. The docs say the following:
Serializes and deserializes an object, or an entire graph of connected objects, in binary format.
This binary format is a .NET-specific implementation detail. And it's very rigid at that, with poor versioning support. It was mainly used in the .NET remoting days, and it's generally considered a bad idea to use it today, as there are much better serializers around.
As you can see, there's no way your C++ app could be able to read that, as it's not in protobuf format.
So throw this method away and replace it with some proper protobuf serializing code, as explained in the protobuf-net docs. You'll need to add [ProtoContract] and [ProtoMember] attributes in your objects. Then you could write something like:
public static byte[] ToByteArray<T>(this T o)
{
if (o == null)
return null;
using (MemoryStream ms = new MemoryStream())
{
ProtoBuf.Serializer.Serialize(ms, o);
return ms.ToArray();
}
}
BinaryFormatter is able to handle serialization simply:
private byte[] TokenToBytes(SessionSecurityToken token)
{
if (token == null)
{
return null;
}
using (var memoryStream = new MemoryStream())
{
var binaryFormatter = new BinaryFormatter();
binaryFormatter.Serialize(memoryStream, token);
return memoryStream.ToArray();
}
}
When I tried replacing BinaryFormatter with protobuf-net:
using (var memoryStream = new MemoryStream())
{
Serializer.Serialize(memoryStream, token);
return memoryStream.ToArray();
}
I get the following exception:
Type is not expected, and no contract can be inferred:
System.IdentityModel.Tokens.SessionSecurityToken
I tried adding:
RuntimeTypeModel.Default.Add(typeof(SessionSecurityToken), true);
Which gets past the exception but I now get a zero byte array.
How do I properly configure protobuf-net to serialize a SessionSecurityToken?
On the flipside, SessionSecurityToken does not have a parameterless constructor.
using (var memoryStream = new MemoryStream(tokenAsBytes))
{
return Serializer.Deserialize<SessionSecurityToken>(memoryStream);
}
Throws a ProtoException:
No parameterless constructor found for SessionSecurityToken
BinaryFormatter is able to do it without any fuss:
using (var memoryStream = new MemoryStream(bytes))
{
var binaryFormatter = new BinaryFormatter();
return (SessionSecurityToken)binaryFormatter.Deserialize(memoryStream);
}
How do I properly configure protobuf-net to deserialize a SessionSecurityToken?
protobuf-net does not claim to be able to serialize every single type; indeed, you would have great difficulty serializing that via most serializers (XmlSerializer, any of the json serializers, DataContractSerializer, etc). BinaryFormatter is in a different category of serializers - and in this particular case, implements custom serialization via ISerializable.GetObjectData(SerializationInfo, StreamingContext).
The constructor thing is a red herring; actually, protobuf-net can bypass constructors completely, and in this particular scenario BinaryFormatter is using a custom serialization constructor via .ctor(SerializationInfo, StreamingContext).
For simple cases, protobuf-net can be configured via attributes or runtime options; for more complex scenarios, surrogates can be used to map between representations - however, in this case I would suggest (looking at the implementation of SessionSecurityToken) that this is more complex than you probably want to maintain.
I would step back a step or two here; most serializers are designed to work with data, not implementation - and work great with DTOs etc. SessionSecurityToken is very much not a DTO, and there is no simple way of switching between them. My strong suggestion here would be: serialize what this represents, not what it is. However, if this is part of an existing complex model and is really really hard to separate out, you could switch back to BinaryFormatter for those bits. I haven't tested this, but consider:
RuntimeTypeModel.Default.Add(typeof(SessionSecurityToken), false)
.SetSurrogate(typeof(BinaryFormatterSurrogate<SessionSecurityToken>));
With:
[ProtoContract]
public class BinaryFormatterSurrogate<T>
{
[ProtoMember(1)]
public byte[] Raw { get; set; }
public static explicit operator T(BinaryFormatterSurrogate<T> value)
{
if(value==null || value.Raw == null) return default(T);
using(var ms = new MemoryStream(value.Raw))
{
return (T)new BinaryFormatter().Deserialize(ms);
}
}
public static explicit operator BinaryFormatterSurrogate<T>(T value)
{
object obj = value;
if (obj == null) return null;
using (var ms = new MemoryStream())
{
new BinaryFormatter().Serialize(ms, obj);
return new BinaryFormatterSurrogate<T> { Raw = ms.ToArray() };
}
}
}
Keep in mind that this simply embeds the output of one serializer as raw data inside another. Fortunately protobuf-net is happy talking binary, so this won't add any noticeable overhead (just the header and length-prefix for the blob) - but it also won't do anything particularly smart or clever with the SessionSecurityToken instances. If this is the only thing you are serializing, it really isn't worth it. If this is just one ugly bump in a larger DTO model, where most of it can serialize nicely - then it might get the job done for you.
I have a legacy app that uses SoapFormatter to persist a graph of objects (maybe 50 different classes). I want to move away from using this as it is deprecated, and increasingly hard to continue to support deserializing from old files as the classes change.
I want to use DataContractSerializer going forward. Does anyone have any suggestions as to a good strategy for migration? I need to continue to be able to deserializing old files written by SoapFormatter...
Thanks
I don't think you want to be limited to a backward-compatible format.
So you will need to distinguish old and new content. And easy method would be :
Old Format: <soapdata>
New Format: <header> <newdata>
And in your new Load() method:
(Try to) Read the header
If a header is found, continue to read the new format
else re-position to begin and use the SOAP formatter to read.
The simplest code would be to try deserialize with DataContractSerializer and fallback to SoapFormatter if it fails.
The save part will always use the DataContractSerializer, so that your new objects or the updated ones will use your new supported version.
public MyContract Deserialize(string file)
{
try
{
using (var stream = loadFile())
{
return loadWithDataContractSerializer(stream);
}
}
catch (SerializationException)
{
using (var stream = openForRead(file))
{
return convertToContract(loadWithSoapFormatter(stream));
}
}
}
private MyContract loadWithDataContractSerializer(Stream s);
private MyOldObject loadWithSoapFormatter(Stream s);
private MyContract convertToContract(MyOldObject obj);
public void Serialize(string file, MyContract data)
{
using (var stream = openForWrite(file))
{
writeWithDataContractSerializer(stream, data);
}
}
Of course, it might be possible to implement a custom logic to allow DataContractSerializer to understant the SoapFormatter structure, but you will have to provide a lot more work.
I just wrote this SerializationHelper class, but I can't believe this is necessary!
using System.IO;
using System.Xml.Serialization;
public static class SerializationHelper
{
public static string Serialize<T>(T obj)
{
var outStream = new StringWriter();
var ser = new XmlSerializer(typeof(T));
ser.Serialize(outStream, obj);
return outStream.ToString();
}
public static T Deserialize<T>(string serialized)
{
var inStream = new StringReader(serialized);
var ser = new XmlSerializer(typeof(T));
return (T)ser.Deserialize(inStream);
}
}
And it's used like this:
var serialized = SerializationHelper.Serialize(myObj);
and:
var myObj = SerializationHelper.Deserialize<MyType>(serialized)
Am I missing something in the .NET framework? This is not rocket science!
In actual fact, the bits where you call the .NET API are these:
var ser = new XmlSerializer(typeof(T));
ser.Serialize(outStream, obj);
var ser = new XmlSerializer(typeof(T));
var obj = (T) ser.Deserialize(inStream);
The rest of the code is your personal specialisation. I don't think that two lines of code is too much for calling an API. You could always condense them, e.g.
(new XmlSerializer(typeof(T))).Serialize(outStream, obj);
var obj = (T) (new XmlSerializer(typeof(T))).Deserialize(inStream);
Purely as an aside, I should point out that I regard storing XML data in string variables as a Code Smell. As soon as you take XML data out of its raw binary form (XDocument, XmlDocument, XPathDocument or any other type of DOM), you run up against encoding issues. What if a developer serialises an object to a string with encoding X, then writes the string to a disk file with encoding Y? Not very safe. Besides which, if encoding X is not UTF-16, how would you even represent the data in a .NET string?
It's useful if you are doing any real amount (>1) of serialization/deserialization within a project. This was the case for me one time, so I just put a similar class in a Utils library, along with other reusable functions.