首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >为什么Json.NET无法序列化X509Certificate2?

为什么Json.NET无法序列化X509Certificate2?
EN

Stack Overflow用户
提问于 2014-02-11 01:38:53
回答 2查看 2.3K关注 0票数 4

每当我尝试用Json.NET序列化一个X509Certificate2实例(没有使用它的ISerializable实现,但选择忽略它)时,Json.NET就会抛出一个异常。

异常消息是“在'System.Security.Cryptography.X509Certificates.X509Certificate2'.上已存在名为'CertContext‘的成员,请使用JsonPropertyAttribute指定另一个名称。”

我写了一个重现它的程序:

代码语言:javascript
复制
using System.Reflection;
using System.Security.Cryptography.X509Certificates;
using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;

internal class Program
{
    private static void Main(string[] args)
    {
        var resolver = new DefaultContractResolver
        {
            IgnoreSerializableInterface = true,
            DefaultMembersSearchFlags =
                BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.GetProperty
        };

        JsonConvert.SerializeObject(new X509Certificate2(), new JsonSerializerSettings {ContractResolver = resolver});
    }
}

经过研究,我注意到X509Certificate2实现了一个名为"CertContext“的属性,该属性在其基类X509Certificate中隐藏了一个同名的方法。我如何才能告诉Json.NET像往常一样只获取派生最多的属性呢?

EN

回答 2

Stack Overflow用户

发布于 2018-06-05 06:58:02

我最近遇到了序列化X509Certificate2实例的需要,以便在两个行为不同的理应相同的环境中比较差异。我能够通过下面的JsonSerializerSettings实现序列化

代码语言:javascript
复制
new JsonSerializerSettings {
    Error = (s, a) => a.ErrorContext.Handled = true,
    ContractResolver = new DefaultContractResolver {
        IgnoreSerializableInterface = true
    }
}

这是一个完整的工作示例,JSON序列化本地机器存储中的第一个证书并打开它:

代码语言:javascript
复制
namespace ConsoleApp1
{
    using System.Diagnostics;
    using System.IO;
    using System.Security.Cryptography.X509Certificates;

    using Newtonsoft.Json;
    using Newtonsoft.Json.Serialization;

    class Program
    {
        static void Main(string[] args)
        {
            var store = new X509Store(StoreName.My, StoreLocation.LocalMachine);

            try
            {
                store.Open(OpenFlags.ReadOnly);

                var cert = store.Certificates[0];

                var path = Path.GetTempFileName();

                File.WriteAllText(
                    path,
                    JsonConvert.SerializeObject(
                        cert, new JsonSerializerSettings {
                            Formatting = Formatting.Indented,
                            // Ignore serializtion errors
                            Error = (s, a) => a.ErrorContext.Handled = true,
                            ContractResolver = new DefaultContractResolver {
                                // Ensures all properties are serialized
                                IgnoreSerializableInterface = true
                            }
                        }
                    )
                );

                Process.Start(path);
            }
            finally
            {
                store.Close();
            }
        }
    }
}
票数 4
EN

Stack Overflow用户

发布于 2020-07-17 00:20:29

要实现这一点,您可以使用转换器:

代码语言:javascript
复制
public class X509Certificate2JsonConverter : JsonConverter
{
    public override bool CanConvert(Type objectType)
    {
        return objectType == typeof(X509Certificate2);
    }

    public override object ReadJson(JsonReader reader,
        Type objectType, object existingValue, JsonSerializer serializer)
    {
        var deserializedRaw = serializer.Deserialize<byte[]>(reader);
        var deserialized = new X509Certificate2(deserializedRaw);
        return deserialized;
    }

    public override void WriteJson(JsonWriter writer,
        object value, JsonSerializer serializer)
    {
        byte[] certData = ((X509Certificate2)value).Export(X509ContentType.Pfx);
        serializer.Serialize(writer, certData);
    }
}

以及对它的测试:

代码语言:javascript
复制
public class CertificateHolder : IDisposable
{
    [JsonConverter(typeof(X509Certificate2JsonConverter))]
    public X509Certificate2 Certificate { get; set; }

    public void Dispose() => Certificate?.Dispose();

    public static X509Certificate2 CreateCertificate()
    {
        var ecdsa = ECDsa.Create();
        var req = new CertificateRequest("cn=foobar", ecdsa, HashAlgorithmName.SHA256);
        var c = req.CreateSelfSigned(DateTimeOffset.Now, DateTimeOffset.Now.AddYears(5));
        return c;
    }
}

[TestFixture]
class X509Certificate2JsonConverterTests
{
    [Test]
    public void Serialization()
    {
        var holder = new CertificateHolder();
        holder.Certificate = CertificateHolder.CreateCertificate();
        var str = JsonConvert.SerializeObject(holder);
        var holderRestored = JsonConvert.DeserializeObject<CertificateHolder>(str);
        var holderStr = holder.Certificate.ToString();
        var holderRestoredStr = holderRestored.Certificate.ToString();
        Assert.AreEqual(holderStr, holderRestoredStr);
        holder.Dispose();
        holderRestored.Dispose();
    }
}
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/21684184

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档