【问题标题】:Json.NET - how to serialize an external class with internal constructor?Json.NET - 如何使用内部构造函数序列化外部类?
【发布时间】:2015-07-20 07:39:08
【问题描述】:

我需要序列化一个类,它的源代码不能改变(把这当作事实),它来自不同的程序集。它只有一个构造函数

public class MyObject
{
    string _s;
    int _i;
    internal MyObject(string s, int i)
    {
        // ...
    }
}

JsonConvert.SerializeObject(object) 当然会因此而失败。我想知道是否有一种方法可以使用 Json.NET 来序列化此类,而无需添加代码甚至标记。

【问题讨论】:

  • 失败时收到的错误信息是什么?我问的原因是,如果 DeserializeObject 与构造函数有关,它不应该抛出异常吗,因为这是它必须再次构造对象的时候。
  • MyObject 类是否密封?你能继承吗?
  • @MarioStoilov 它没有密封。
  • 你可以尝试继承类并在新类中定义一个无参数构造函数
  • @MarioStoilov 你不能在 C# 中做到这一点。构造函数是内部的。

标签: c# oop serialization json.net private-constructor


【解决方案1】:

如果你有一个无参数构造函数,你应该可以通过添加以下设置来做到这一点:

JsonSerializerSettings settings = new JsonSerializerSettings()
{
    ConstructorHandling = ConstructorHandling.AllowNonPublicDefaultConstructor
};

var serializedJson = JsonConvert.DeserializeObject<MyObject>(jsonString, settings);

问题编辑后更新:

如果你没有 任何 public 构造函数并且你没有无参数构造函数,那么我只知道 2 个选项:

  1. [JsonConstructor] 属性添加到您的 internal 构造函数(在您的情况下这似乎不是一个选项,因为您无法编辑类)。
  2. 创建一个具有相似属性的代理类(不那么优雅,但不需要更改类)。

【讨论】:

  • 无法使用建议的解决方案,因为源代码无法更改(将此视为事实),如问题中所述。
【解决方案2】:

您应该使用custom JsonConverter

解决方案类似于

public class MyObjectProxy
{
    public string s { get; set; }
    public int i { get; set; }
}

public class MyObjectJsonConverter : JsonConverter
{
    public override void WriteJson(
        JsonWriter writer, object value, JsonSerializer serializer)
    {
        // Create an instance of MyObjectProxy, copy values from the
        // instance of MyObject, write JSON from the MyObjectProxy.
    }

    public override object ReadJson(
        JsonReader reader, Type type, object value, JsonSerializer serializer)
    {
        // Deserialize MyObjectProxy, create an instance of MyObject,
        // copy properties from the deserialized MyObjectProxy.
    }

    public override bool CanConvert(Type type)
    {
        return typeof(MyObject).IsAssignableFrom(type);
    }
}

【讨论】:

    【解决方案3】:

    您可以使用具有类似属性的代理类:

    public sealed class TargetClass{
        public static readonly TargetClass tc = new TargetClass();
        public int Id;
        public string SomeName;
        private TargetClass(){
            this.Id=50;
            this.SomeName="My, What Bastardry";
        }
    }
    public class ProxyClass{
        public int Id {get; set;}
        public string SomeName {get; set;}
        public ProxyClass(){
        }
        public ProxyClass(int id, string somename){
            Id = id;
            SomeName = somename;
        }
    }
    public class Program
    {
        public static void Main()
        {
            TargetClass tgt = TargetClass.tc;
            ProxyClass pc = new ProxyClass(tgt.Id,tgt.SomeName);
            string s = JsonConvert.SerializeObject(pc);
            Console.WriteLine(s);
        }
    }
    

    【讨论】:

    • 使用反射和代理对象的快速而肮脏的示例,但您可以将其与其他人提到的自定义 JsonConvertors 结合使用:dotnetfiddle.net/OtOXSm
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-12-12
    • 1970-01-01
    • 1970-01-01
    • 2010-11-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多