I'm having an issue with JSON and de-serialisation. I've got a live production code which uses a message object to pass information around from one system to another. The ID of the message is very important as this is used to identify it. We also don't want anyone Setting the ID's and as such made it a private setter.
My problem comes when trying to deserialise the JSON object and the ID is not set. (obviously because it's private)
Does any one have a good suggestion as the best way to proceed? I've tried using Iserialisation and it's ignored. I've tried using DataContract but this fails because of the external system we are getting the data from.
My only option on the table at the moment is to make the ID and TimeCreated fields have public setters.
I have an object as such
Message
{
public Message()
{
ID = Guid.NewGuid();
TimeCreated = DateTime.Now();
}
Guid ID { get; private set; }
DateTime TimeCreated { get; private set; }
String Content {get; set;}
}
Now I'm using the following code:
var message = new Message() { Content = "hi" };
JavaScriptSerializer jss = new JavaScriptSerializer();
var msg = jss.Serialize(message);
var msg2 = jss.Deserialize<Message>(msg);
Assert.IsNotNull(msg2);
Assert.AreEqual(message.ID, msg2.ID);
The Id and Time created fields do not match because they are private. I've also tried internal and protected but no joy here either.
The full object has a constructor which accepts an ID and Date time to set these when loading them out of the DB.
Any help will be greatly appreciated.
Thank you
A common way to deserialize JSON is to first create a class with properties and fields that represent one or more of the JSON properties. Then, to deserialize from a string or a file, call the JsonSerializer. Deserialize method.
The quickest method of converting between JSON text and a .NET object is using the JsonSerializer. The JsonSerializer converts .NET objects into their JSON equivalent and back again by mapping the .NET object property names to the JSON property names and copies the values for you.
JSON is a format that encodes objects in a string. Serialization means to convert an object into that string, and deserialization is its inverse operation (convert string -> object).
PropertyName Property. Gets or sets the name of the property. Namespace: Newtonsoft.Json.Serialization.
You can use the DataContractJsonSerializer
instead of the JavaScriptSerializer
. You will need to decorate your class with some data contract attributes.
[DataContractAttribute()]
public class Message
{
public Message()
{
ID = Guid.NewGuid();
TimeCreated = DateTime.Now;
}
[DataMemberAttribute()]
Guid ID { get; private set; }
[DataMemberAttribute()]
DateTime TimeCreated { get; private set; }
[DataMemberAttribute()]
String Content {get; set;}
}
Generic serialization helper methods
public static string ToJsonString(object obj)
{
DataContractJsonSerializer serializer = new DataContractJsonSerializer(obj.GetType());
using (MemoryStream ms = new MemoryStream())
{
serializer.WriteObject(ms, obj);
StringBuilder sb = new StringBuilder();
sb.Append(Encoding.UTF8.GetString(ms.ToArray()));
return sb.ToString();
}
}
public static T ToObjectFromJson<T>(string json)
{
DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(T));
using (MemoryStream ms = new MemoryStream(Encoding.UTF8.GetBytes(json)))
{
return (T) serializer.ReadObject(ms);
}
}
In your case, you can deserialize using:
Message msg = ToObjectFromJson<Message>(jsonString);
I think having a new layer of abstraction in between your json and your Dto is your best bet.
MessageViewModel
{
public MessageViewModel()
{
}
Guid ID { get; set; }
DateTime TimeCreated { get; set; }
String Content {get; set;}
}
static MessageFactory
{
public static Message Build(MessageViewModel viewModel)
{
var result = new Message(viewModel.ID, viewModel.TimeCreated);
result.Content ....
etc etc
return result;
}
}
JavaScriptSerializer jss = new JavaScriptSerializer();
MessageViewModel viewModel = jss.Deserialize<MessageViewModel>(jsonString);
var message = MessageFactory.Build(viewModel);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With