3

I've been serializing custom type which has some internal properties but when serializing, it seems that using System.Web.Script.Serialization.JavaScriptSerializer serialize method do not serialize internal properties (as it skips the internal property in serialized string). It can easily be understandable from the following code and output :

public class MyClass
{
    public string Property1 { get; set; }

    internal string Property2 { get; set; }

    public string Property3 { get; set; }
}

JavaScriptSerializer mySerializer = new JavaScriptSerializer();
string jsonString = mySerializer.Serialize(new MyClass()
{
            Property1 = "One",
            Property2 = "Twp",
            Property3 = "Three"
});

The jsonString has following value :

{"Property1":"One","Property3":"Three"}

In output, you can see that serialized string do not have Property2 which is internal property. Is there something logic behind it for not supporting internal property in serialization?

What would be the workaround to serialize internal property(except changing internal to public modifier)?

Akash KC
  • 16,057
  • 6
  • 39
  • 59
  • It seems counter-intuitive to have a piece of data marked as inaccessible outside of the assembly (`internal`) also be included by default in a process of sending data to another location entirely (serialization). – Will Ray Apr 14 '16 at 16:33
  • @Will: It is quite confusing to understand, why did MS had taken consideration of cross assembly issue in serialization as it can easily seen that serialization performed in same assembly quite often – Akash KC Apr 14 '16 at 17:02

2 Answers2

4

It's simply not supported in System.Web.Script.Serialization.JavaScriptSerializer.

I'd recommend you switch to Json.NET. All you need to do in that case is mark the internal property with the json property attribute and it'll get picked up by the Json.NET serializer.

[Newtonsoft.Json.JsonProperty]
internal string Property2 { get; set; }

It's worth noting that Json.NET is vastly more performant

50% faster than DataContractJsonSerializer, and 250% faster than JavaScriptSerializer.

and has far more configuration options and is currently the default choice by Microsoft for .NET.

Per your request in the comments, it IS possible to do this with a .NET FCL library if you use DataContractJsonSerializer, although that presents it's own set of pain in terms of the api and the need to mark every single class and property with [DataContract] and [DataMember] respectively.

using System.Runtime.Serialization;
using System.Runtime.Serialization.Json;

var instance = new MyClass {
        Property1 = "One",
        Property2 = "Twp",
        Property3 = "Three"
};

var ser = new DataContractJsonSerializer(instance.GetType());

using (MemoryStream ms = new MemoryStream())
{
    ser.WriteObject(ms, instance);
    string jsonData = Encoding.Default.GetString(ms.ToArray());
}

[DataContract]
public class MyClass
{
    [DataMember]
    public string Property1 { get; set; }
    [DataMember]
    internal string Property2 { get; set; }
    [DataMember]
    public string Property3 { get; set; }
}

This will correctly output

{"Property1":"One","Property2":"Twp","Property3":"Three"}

although I personally believe you're being dogmatic for zero value and creating a great deal of pain for yourself. I'd still highly recommend you switch to a more modern serializer.

David L
  • 32,885
  • 8
  • 62
  • 93
  • I am just curious to know about why don't it get supported in System.Web.Script.Serialization.JavaScriptSerializer. Is there any reason for not supporting it? Yeah, I can do it with Newtonsoft as you specified but for simple serialzation/deserailzation, I thought JavaScriptSerializer would be fine. – Akash KC Apr 14 '16 at 16:34
  • 1
    Because when Microsoft wrote it they didn't take it into account. You'd have to ask whoever wrote the serializer class :). That said, there's no reason to use JavaScriptSerializer anymore. It's deprecated, slow, inefficient and quirky. You should switch to a more modern serializer. – David L Apr 14 '16 at 16:35
  • Do .NET FCL itself has any other way to serialize/deserialize internal properties? – Akash KC Apr 14 '16 at 16:42
  • Indeed, the app I've been developing is smaller(interms of size, my app : 10KB and Newtonsoft : 475KB) so I am hesitate to use third party library(Newtonsoft) to do simple serialization job. The question is just for my curiosity, otherwise your answer is really great. – Akash KC Apr 14 '16 at 17:26
  • I'd recommend a smaller serializer in that case then, if possible. Something like https://github.com/kevin-montrose/Jil might work well for you, although that might still be too large. It sounds like your perf concerns come in the way of total library size, not speed which means you might be stuck with DataContractJsonSerializer. – David L Apr 14 '16 at 17:28
  • Thanks for the effort. Will definitely look into Jil library which I've heard for first time :( – Akash KC Apr 15 '16 at 04:51
1

The documentation for JavaScriptSerializer is on the sparse side, I couldn't find anything about how that type deals with access modifiers.

internal hides Property2 from types outside your assembly, so I presume there is some code in JavaScriptSerializer that asks "What properties can I see on this object?"

That is a tricky question, as you've seen, and more robust serialization systems ask the better-documented question "What properties on this object are annotated with serialization hints?"

See JSON.net (as recommended in the JavaScriptSerializer docs) and DataContractJsonSerializer

Matt Stephenson
  • 8,442
  • 1
  • 19
  • 19
  • Do .NET FCL itself has any other way to serialize/deserialize internal properties? – Akash KC Apr 14 '16 at 16:42
  • `DataContractJsonSerializer` should respect all properties tagged with `DataMember` regardless of their access modifier, IIRC. – Matt Stephenson Apr 15 '16 at 13:42
  • 1
    Also, @LolCoder아카쉬 I get the desire to stick to things in the base classes. I've worked in situations where the effort to install libs on production quickly becomes greater than the effort to re-invent wheels from base classes. – Matt Stephenson Apr 15 '16 at 13:47