序列化为JSON

时间:2016-04-15 21:10:30

标签: c# json.net

我有一个扁平的对象,我想分组成几个部分,以便更容易解析。这是我班级目​​前的基本概念:

class Populations {
  public string US { get; set; }
  public string Canada { get; set; }

  public string Germany { get; set; }
  public string England { get; set; }
}

但这是我希望在填充数据时将其序列化:

{
  "Populations": {
    "North America": {
      "US": "318 million",
      "Canada": "35 million" 
    },
    "Europe": {
      "Germany": "80 million",
      "England": "53 million"
    }
  }
}

我要做的是将我的国家包装成大陆而不实际创建新的大陆类。这可能是使用像Json.Net这样的工具,还是只需创建一个包含两个属性的NorthAmerica类,然后创建一个具有两个属性的Europe类?是否有可能存在注释以允许我将这些属性组合在一起?

3 个答案:

答案 0 :(得分:2)

Json.Net中没有内置机制来执行此描述的分组;但是,如果这是你真正想要的,你可以自定义JsonConverter。这样的事情可能有用:

class GroupAttribute : Attribute
{
    public string Name { get; set; }
    public GroupAttribute(string name)
    {
        Name = name;
    }
}

class GroupingConverter : JsonConverter
{
    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        JObject obj = new JObject();
        Type type = value.GetType();
        foreach (PropertyInfo pi in type.GetProperties())
        {
            JToken propVal = JToken.FromObject(pi.GetValue(value));
            GroupAttribute group = pi.GetCustomAttribute<GroupAttribute>();
            if (group != null)
            {
                JObject groupObj = (JObject)obj[group.Name];
                if (groupObj == null)
                {
                    groupObj = new JObject();
                    obj.Add(group.Name, groupObj);
                }
                groupObj.Add(pi.Name, propVal);
            }
            else
            {
                obj.Add(pi.Name, propVal);
            }
        }

        JObject wrapper = new JObject(new JProperty(type.Name, obj));
        wrapper.WriteTo(writer);
    }

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

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

    public override bool CanConvert(Type objectType)
    {
        // CanConvert is not called when a [JsonConverter] attribute is applied
        return false;
    }
}

然后,您可以将Populations类标记为:

[JsonConverter(typeof(GroupingConverter))]
class Populations 
{
    [Group("North America")]
    public string US { get; set; }
    [Group("North America")]
    public string Canada { get; set; }

    [Group("Europe")]
    public string Germany { get; set; }
    [Group("Europe")]
    public string England { get; set; }
}

最后,像这样序列化:

string json = JsonConvert.SerializeObject(populations, Formatting.Indented);

小提琴:https://dotnetfiddle.net/EPiJue

答案 1 :(得分:1)

您可以创建课程NorthAmericaEurope,或者您可以执行以下操作:

class Continent{
    string Type { get; set; }
    ICollection<Country> Countries { get; set; }
}

这当然需要您所有国家/地区都有共同的基类或接口。

答案 2 :(得分:0)

看到你的JSON没有数组,你是当前的类使得这个json无法创建,除非你创建另一个具有你想要的结构的类或者将它选择为动态对象。

如果你必须严格遵守这个JSON,我会鼓励你制作一个具有类似

结构的不同人口类别
class Populations {
    public NorthAmerica NorthAmerica { get; set; }
    public Europe Europe { get; set; }
}

class NorthAmerica{
    public string US { get; set; }
    public string Canada { get; set; }
}

class Europe{
    public string Germany{ get; set; }
    public string England{ get; set; }
}