【问题标题】:How to fake the type in JSON.NET when serializing out?序列化时如何伪造 JSON.NET 中的类型?
【发布时间】:2011-10-31 20:16:56
【问题描述】:

假设我有

public class Person
    {
        public string FirstName { get; set; }
        public string LastName { get; set; }
        public string PhoneNumber { get; set; }
    }

现在,如果我创建一个像...这样的匿名类型

var p = new Person() {FirstName = "bob",
                      LastName = "builder",
                      PhoneNumber = "0800 YESWECAN"};

var anon = new {p.FirstName, p.LastName};

使用 JSON.NET,当您拥有 TypeNameHandling = TypeNameHandling.Objects 时,它将序列化(然后用于反序列化)类型。我想要做的是伪造 annoymous 类中的类型,这样当它被序列化时,它看起来像一个“Person”对象。

有没有很好的简单方法来做到这一点?

注意:它必须在 json ( $type ) 中有 Json.Net 类型信息。所以 LBs 的回答并不能解决问题,实际上我可以使用 .net frameworks json 工具来做到这一点。

【问题讨论】:

  • 有什么原因不能使用new Person { FirstName = "", LastName = "" }
  • 是的......仍然会有一个带有“PhoneNumber”的对象。对于这种情况,我不希望电话号码序列化(这是一个人为的例子来问这个问题,实际上,对象模型很复杂)。我更新了示例以尝试使其更清晰

标签: c# json.net


【解决方案1】:

你可以序列化为

string str = JsonConvert.SerializeObject(new { FirstName = "aaa", LastName = "bbb" })

你会得到一个看起来像 Person 对象的字符串

{"FirstName":"aaa","LastName":"bbb"}

由于 Json 不包含类型信息,您可以将其反序列化回 Person

var person = JsonConvert.DeserializeObject(str, typeof(Person));

【讨论】:

  • 我不相信这是正确的答案。我认为OP需要将$type设置为Person的对象序列化,以便以后可以反序列化而无需知道对象类型。
  • I don't believe this is the right answer , this isn't the right answer @KeithNicholas @CAbbott 这有什么问题?你真正期待什么?证明你的答案
  • 因为当对象模型比较复杂时,你需要类型信息(尤其是sublassing)。我的问题是关于如何用匿名类型伪造类型信息。
  • because when the object model is more complex, you need the type information 不是答案。你可能不需要它。只要问你真正的问题并得到解决方案。它认为这是某种 XY 问题perlmonks.org/?node_id=542341
  • 来自 Json.NET 文档:TypeNameHandling 控制 Json.NET 在序列化期间是否包含 .NET 类型名称,并从该属性中读取 .NET 类型名称以确定在反序列化期间创建什么类型。
【解决方案2】:

为了伪造它,我可以引入一个合同来在输出 json 时更改属性名称...例如...

 public class FakeTypeContractResolver : DefaultContractResolver
    {        
        protected override string ResolvePropertyName(string propertyName)
        {
            return propertyName == "_type_" ? "$type" : propertyName;
        }
    }

因此,如果您将 json.net 反序列化器设置设置为

TypeNameHandling = TypeNameHandling.Objects
TypeNameAssemblyFormat = FormatterAssemblyStyle.Full

你可以像下面这样创建一个令人讨厌的类型,

var x = new 
{
     _type_ = typeof(Person).AssemblyQualifiedName,
     p.FirstName, 
     p.LastName
}

这将在类型信息中伪装成“Person”,这意味着如果您反序列化它,您将获得一个 person 对象。

注意:序列化器到 json 设置必须设置为在伪造时不序列化类型信息。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2023-03-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多