21

I haven't been able to find the answer to this anywhere, but when I try to serialize a struct or class with static or const member variables, they don't serialize by default. If I try to force serialization by setting MemberSerialization.OptIn, I get an error.

ex.

[JsonObject(MemberSerialization.OptIn)]
public class Test
{    
    [JsonProperty]
    public int x = 1;

    [JsonProperty]
    public static int y = 2;
}

If I try to serialize this class with:

Test t = new Test();
string s = JsonConvert.SerializeObject( t );

I get the error Error getting value from 'y' on 'Test'. The same happens if y is const.

My theory is that static and const values are stored somewhere special in memory, and for some reason the Json serializer dies trying to access them. That's entirely a hunch though, and I see nothing in the C# Reference for Static that's of any help. I'm relatively new to C# - and this is really a curiosity question more than anything at this point.

11
  • 2
    It is not related to some memory. If you consider serialization as taking the snapshot of an instance of a class, static variables are not part of instances. Commented Jun 20, 2014 at 22:42
  • I can't imagine why anyone would need to serialize static and even less so const as a part of JSON object. With const it is especially interesting... how do you deserialize into a constant? Commented Jun 20, 2014 at 22:45
  • There are other use case to serializing AS JSON than deserializing back to the same type (for example, using a serialized C# object in javascript). So you could need to serialize it if it's part of the data you're interested in and the class itself isn't available wherever you're using the json Commented Jun 20, 2014 at 22:52
  • 4
    @Stilgar then you're not very imaginative my friend. The JSON gets sent to our server. The server deals with the data in both python and javascript. The static value is a version identifier that tells the server what client version this is, so it may treat various clients differently. That should be static data. I used readonly and initialized the variable within the class definition, making it instance data, but really, IMO a version specifier should be static. Also the question says serialize not deserialize. Commented Jun 20, 2014 at 22:58
  • 1
    @L.B yep, makes perfect sense when I consider it that way. I guess it's kind of a dumb question now that I look at it since I also can't access the value y using t.y... Oh well. Sometimes dumb questions need to be asked... Commented Jun 20, 2014 at 23:01

4 Answers 4

30

It could certainly serialize the static variable if it wanted to. Serialization is done by inspecting objects and types with the Reflection APIs, and those APIs allow you to do "anything" -- there is no technical reason these values cannot be serialized.

There is, however, a logical reason not to support this by default: it doesn't make much sense. You are serializing an instance, and static or const members are not logically part of an instance but of the class as a whole.

That said, you can still serialize static member if it's a property:

[JsonProperty]
public static int y { get; set; } // this will be serialized

And of course you can completely override the serializer's behavior by creating a custom JsonConverter.

Sign up to request clarification or add additional context in comments.

1 Comment

Thanks. At first I was surprised, not so much that the default was to leave static and const members out, as that my attempt to force them in gave a Runtime error. Good to know that static properties can be serialized.
15

As of Json.NET 6.0.4, static and const member variables, as well as static properties, will be serialized when marked with [JsonProperty]. From the release notes:

  • Fix - Fixed serializing static fields

Thus serializing the following class:

[JsonObject(MemberSerialization.OptIn)]
public class Test
{    
    [JsonProperty]
    int x = 1;

    [JsonProperty]
    static int y = 2;

    [JsonProperty]
    const int z = 333;
}

Produces {"x":1,"y":2,"z":333}. Example fiddle.

Comments

6

Try this:

using Newtonsoft.Json;
using System.Collections.Generic;
using System.Linq;

public static string SerializeStaticClass(System.Type a_Type)
{
        var TypeBlob = a_Type.GetFields().ToDictionary(x => x.Name, x => x.GetValue(null));
        return JsonConvert.SerializeObject(TypeBlob);
}

I did that to serialize all of our static class constants out to a JS file, then bundled that file into an angular app. You attach the generated js objects to $rootScope and all the angular code has access to the constants.

hat tip here

Comments

1

If you need a static member (or const) to be serialized on each instance, you could use a private instance-level accessor as a workaround:

[JsonObject(MemberSerialization.OptIn)]
public class Test
{
    [JsonProperty]
    public int x = 1;

    // static member we want serialized with each instance
    public static int y = 2;

    // private accessor to allow Json.net to serialize the static member
    [JsonProperty("y")]
    private int y1 { get { return y; } }
}

Should you need to deserialize to this class as well, this approach will prevent Json.Net from overwriting the static member while still allowing your own code to modify it if needed.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.