Daniel Eugen
Daniel Eugen

Reputation: 2780

Json.Net setting property name as numbers

Is there a short, more clean way to achieve this ?

public class Sidebar
{
    [JsonProperty("0")]
    public string Hurry = "hurry";

    [JsonProperty("1")]
    public string Dont_Spam_This_Button = "don't spam this button";

    [JsonProperty("2")]
    public string Navigation = "navigation";

    [JsonProperty("3")]
    public string Overview = "overview";

i want to objects to be numbered so is there a way to do that programatically instead of using attributes and manually counting ?

Upvotes: 1

Views: 149

Answers (2)

Brian Rogers
Brian Rogers

Reputation: 129687

Yes, you can get the result you want using a custom JsonConverter like this one:

class NumberedPropertiesConverter : JsonConverter
{
    public override bool CanConvert(Type objectType)
    {
        return true;
    }

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        JObject jo = new JObject();
        int count = 0;

        foreach (MemberInfo member in value.GetType().GetMembers())
        {
            object memberVal = null;
            if (member.MemberType == MemberTypes.Field)
            {
                memberVal = ((FieldInfo)member).GetValue(value);
            }
            else if (member.MemberType == MemberTypes.Property)
            {
                memberVal = ((PropertyInfo)member).GetValue(value);
            }
            else
            {
                continue;
            }

            JToken token = memberVal != null ? JToken.FromObject(memberVal, serializer) : null;
            jo.Add(count.ToString(), token);
            count++;
        }

        jo.WriteTo(writer);
    }

    public override bool CanRead
    {
        get { return false; }
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        throw new NotImplementedException();
    }
}

To use the converter, just mark your class with a [JsonConverter] attribute specifying the type of the custom converter:

[JsonConverter(typeof(NumberedPropertiesConverter))]
public class Sidebar
{
    ...
}

One important note: the properties/fields will be numbered according to the order returned by the Type.GetMembers() method. Generally, this will match the order declared in the class; however, if you have a mix of public properties and public fields, then all of the properties will be returned before all of the fields.

Here is a demo:

public class Program
{
    public static void Main()
    {
        Sidebar sb = new Sidebar();
        string json = JsonConvert.SerializeObject(sb, Formatting.Indented);
        Console.WriteLine(json);
    }
}

[JsonConverter(typeof(NumberedPropertiesConverter))]
public class Sidebar
{
    public string Foo { get { return "foo property"; } }
    public string Hurry = "hurry";
    public string Dont_Spam_This_Button = "don't spam this button";
    public string Navigation = "navigation";
    public string Overview = "overview";
    public string Bar { get { return "bar property"; } }
}

Output:

{
  "0": "foo property",
  "1": "bar property",
  "2": "hurry",
  "3": "don't spam this button",
  "4": "navigation",
  "5": "overview"
}

Fiddle: https://dotnetfiddle.net/aZ51qv

Upvotes: 1

Tracker1
Tracker1

Reputation: 19334

What you are doing will give you something like {"0":"hurry",...,"3":"overview"} when what you want is more like ["hurry",...,"overview"]

What you can do, is create a custom converter/serializer, or if you don't need automatic serialization/deserialization in .net, just serialize an object[] array in a class method...

public string AsJson()
{
  return JsonConvert.SerializeObject(new object[] {
    Hurry, Dont_Spam_This_Button, Navigation, Overview
  });
}

Upvotes: 0

Related Questions