JSON序列化对象与内部属性

32

我有一些包含内部属性的类,我想将它们序列化为json。我该如何实现?例如:

public class Foo
{
    internal int num1 { get; set; }
    internal double num2 { get; set; }
    public string Description { get; set; }

    public override string ToString()
    {
        if (!string.IsNullOrEmpty(Description))
            return Description;

        return base.ToString();
    }
}

使用以下方式保存它:

Foo f = new Foo();
f.Description = "Foo Example";
JsonSerializerSettings settings = new JsonSerializerSettings() { TypeNameHandling = TypeNameHandling.All };

 string jsonOutput = JsonConvert.SerializeObject(f, Formatting.Indented, settings);

 using (StreamWriter sw = new StreamWriter("json_file.json"))
 {
     sw.WriteLine(jsonOutput);
 }
我明白了。这是需要翻译的内容:

I get

{  
"$type": "SideSlopeTest.Foo, SideSlopeTest",
"Description": "Foo Example"
}

4
通常,内部属性不应超出当前程序集的边界而进行序列化。为什么需要这样做呢?如果你想要一个合适的 JSON 表示,你可能需要创建一个数据传输对象(DTO),将你的内部/私有信息映射到该对象上,然后进行序列化。 - Darin Dimitrov
+1 DarinDimitrov所说的没错。但是如果你真的想这么做,我相信你需要子类化DefaultContractResolver,以便它也能查看非公共属性。 - s.m.
3
只需使用[JsonProperty()]属性进行标记即可。 - dbc
如果该类也是内部的,请使用[JsonObject()]进行标记。 - CAD bloke
1个回答

51

使用[JsonProperty]属性标记要与序列化一起使用的内部属性:

public class Foo
{
    [JsonProperty]
    internal int num1 { get; set; }
    [JsonProperty]
    internal double num2 { get; set; }

    public string Description { get; set; }

    public override string ToString()
    {
        if (!string.IsNullOrEmpty(Description))
            return Description;

        return base.ToString();
    }
}

之后,为了进行测试:

Foo f = new Foo();
f.Description = "Foo Example";
f.num1 = 101;
f.num2 = 202;
JsonSerializerSettings settings = new JsonSerializerSettings() { TypeNameHandling = TypeNameHandling.All };

var jsonOutput = JsonConvert.SerializeObject(f, Formatting.Indented, settings);

Console.WriteLine(jsonOutput);

我得到了以下输出:

{
  "$type": "Tile.JsonInternalPropertySerialization.Foo, Tile",
  "num1": 101,
  "num2": 202.0,
  "Description": "Foo Example"
}

(其中"Tile.JsonInternalPropertySerialization"和"Tile"是我使用的命名空间和程序集名称)。

另外,当使用TypeNameHandling时,请注意来自Newtonsoft文档的这个警告:

当您的应用程序使用一个值而不是None进行反序列化时,应谨慎使用TypeNameHandling来反序列化来自外部源的JSON。传入类型应该在反序列化时使用自定义SerializationBinder进行验证。

关于为什么可能需要这样做的讨论,请参见Newtonsoft Json中TypeNameHandling的警告以及由于Json.Net TypeNameHandling自动化,外部json容易受到攻击?


我刚刚删除了我的回答,因为我不知道内部属性在程序集外部是不可访问的。但是,序列化器如何能够跨程序集访问这些属性呢?这不是一种安全问题吗? - esmoore68
5
这句话的意思是:序列化器使用反射。可参考以下链接:https://dev59.com/eXI_5IYBdhLWcg3wAeLl 和 https://dev59.com/zIrda4cB1Zd3GeqPQsIi。 - dbc
除了@dbc的答案之外,报告的内容对于内部可见性类和私有可见性(嵌套)类仍然有效。 - Giacomo Pirinoli

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接