使用Newtonsoft.Json

时间:2017-05-12 00:24:45

标签: c# json json.net

我有以下简单的课程

class MyType {
    string JsonData { get; set;}

    string OtherProperty { get; set; }
}

其中JsonData包含我希望插入序列化类输出的格式化JSON:

"Prop1":"Value1",
"Prop2":"Value2",
"Prop3":"Value3"

我希望将其序列化为

{
    <JsonData>,
    "OtherProperty": ""
}

我已尝试为该字段使用自定义JsonConverter,但我找不到删除属性名称序列化的方法:

{
    "JsonData": <JsonData>,
    "OtherProperty": ""
}

所以基本上我只需要从输出中删除"JsonData":(最好不要使用string.Replace()

1 个答案:

答案 0 :(得分:2)

您可以使用自定义JsonConverter执行此操作,但必须使转换器处理整个MyType类,而不仅仅是JsonData属性。正如您所见,无法在仅处理该属性的转换器中省略属性名称。

以下是我编写转换器的方法:

class MyTypeConverter : JsonConverter
{
    public override bool CanConvert(Type objectType)
    {
        return objectType == typeof(MyType);
    }

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        MyType mt = (MyType)value;
        JObject jo = new JObject();

        if (!string.IsNullOrWhiteSpace(mt.JsonData))
        {
            // JsonData is assumed to contain pre-formatted, comma-separated, JSON properties
            jo.Add(JObject.Parse("{" + mt.JsonData + "}").Properties());
        }

        foreach (PropertyInfo prop in typeof(MyType).GetProperties()
                 .Where(p => p.CanRead && p.Name != "JsonData"))
        {
            object val = prop.GetValue(mt, null);
            jo.Add(prop.Name, val != null ? JToken.FromObject(val, serializer) : JValue.CreateNull());
        }

        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();
    }
}

要使用转换器,只需使用[JsonConverter]属性注释您的类,如下所示:

[JsonConverter(typeof(MyTypeConverter))]
class MyType
{
    ...
}

演示小提琴:https://dotnetfiddle.net/bu0NgC

在介绍了上述内容之后,我应该指出这可能不是最佳解决方案,具体取决于预格式化JSON属性的来源。如果它们来自您控制之外的第三方,那么您使用转换器的设计可能就足够了。但是,如果您要在自己的某个位置创建预格式化的JSON属性作为在MyType类中使用动态属性的方法,那么绝对是更好的方法。

您可以将JsonData声明为Dictionary<string, object>,而不是使用字符串,并使用特殊的[JsonExtensionData]属性对其进行标记:

class MyType 
{
    public MyType()
    {
        JsonData = new Dictionary<string, object>();
    }

    [JsonExtensionData]
    public Dictionary<string, object> JsonData { get; set;}

    public string OtherProperty { get; set; }
}

然后,只需将动态属性作为键值对添加到字典中:

MyType mt = new MyType();
mt.JsonData.Add("Prop1", "Value1");
...

序列化MyType时,字典KVP将自动添加为JSON对象的属性,就像OtherProperty一样。不需要转换器!

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

相关问题