简体   繁体   中英

How to serialize static or const member variables using JSON.NET?

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.

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 .

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 .

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

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM