Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to serialize static properties in JSON.NET without adding [JsonProperty] attribute

Tags:

c#

json.net

Is it possible to serialize static properties with JSON.NET without adding [JsonProperty] attribute to each property. Example class:

public class Settings
    {
        public static int IntSetting { get; set; }
        public static string StrSetting { get; set; }

        static Settings()
        {
            IntSetting = 5;
            StrSetting = "Test str";
        }
    }

Expected result:

{
  "IntSetting": 5,
  "StrSetting": "Test str"
}

Default behavior skips static properties:

var x = JsonConvert.SerializeObject(new Settings(), Formatting.Indented);
like image 448
Milos Avatar asked May 12 '15 14:05

Milos


2 Answers

You can do this with a custom contract resolver. Specifically you need to subclass DefaultContractResolver and override the GetSerializableMembers function:

public class StaticPropertyContractResolver : DefaultContractResolver
{
    protected override List<MemberInfo> GetSerializableMembers(Type objectType)
    {
        var baseMembers = base.GetSerializableMembers(objectType);

        PropertyInfo[] staticMembers = 
            objectType.GetProperties(BindingFlags.Static | BindingFlags.Public);

        baseMembers.AddRange(staticMembers);

        return baseMembers;
    }
}

Here all we're doing is calling the base implementation of GetSerializableMembers, then adding public static properties to our list of members to serialize.

To use it you can create a new JsonSerializerSettings object and set the ContractResolver to an instance of the StaticPropertyContractResolver:

var serializerSettings = new JsonSerializerSettings();

serializerSettings.ContractResolver = new StaticPropertyContractResolver();

Now, pass those settings to JsonConvert.SerializeObject and everything should work:

string json = JsonConvert.SerializeObject(new Settings(), serializerSettings);

Output:

{
  "IntSetting": 5,
  "StrSetting": "Test str"
}

Example: https://dotnetfiddle.net/pswTJW

like image 81
Andrew Whitaker Avatar answered Nov 05 '22 20:11

Andrew Whitaker


A more complicated way to solve this:

Solution 1:

public class Settings
{
    int intsetting { get; set; } /*= 0;*/ // commented only allowed in C# 6+
    string strsetting { get; set; } /*= "";*/

    public int IntSetting { get { return intsetting; } set { intsetting = value; } }
    public string StrSetting { get { return strsetting; } set { strsetting = value; } }

    static Settings()
    {
        IntSetting = 5;
        StrSetting = "Test str";
    }
}

Solution 2: (less complicated)

public class Settings
{
    [JsonProperty]
    public static int IntSetting { get; set; }

    [JsonProperty]
    public static string StrSetting { get; set; }

    static Settings()
    {
        IntSetting = 5;
        StrSetting = "Test str";
    }
}

Adding the [JsonProperty] to all variables would be the easyest way of solving this, but when you don't want to use it Solution 1 would fit best for you.

like image 41
cramopy Avatar answered Nov 05 '22 20:11

cramopy