Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

JSON deserialise to an object with a private setter

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

like image 281
Andrew Newland Avatar asked May 11 '11 07:05

Andrew Newland


People also ask

How do I deserialize JSON to an object?

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.

Which JSON method is used to deserialize the data?

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.

What is the difference between serialize and deserialize JSON?

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).

What is JsonProperty PropertyName?

PropertyName Property. Gets or sets the name of the property. Namespace: Newtonsoft.Json.Serialization.


2 Answers

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);
like image 97
Lee Gunn Avatar answered Oct 03 '22 21:10

Lee Gunn


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);
like image 33
David Avatar answered Oct 03 '22 22:10

David