【问题标题】:JsonSerialization of custome media type, data won't be deserialized自定义媒体类型的JsonSerialization,数据不会被反序列化
【发布时间】:2018-07-03 09:11:21
【问题描述】:

嘿,我正在尝试反序列化某些服务发送到我的端点的 json 流。 问题是该服务向我发送自定义媒体类型的数据,即:

应用程序/vnd.docker.distribution.manifest.v2+json

例如,我从内存中捕获的流,然后保存在文件中:

{
   "events": [
      {
         "id": "7a604759-812c-421a-a182-3928b9eb66d6",
         "timestamp": "2018-07-03T09:04:37.617519518Z",
         "action": "push",
         "target": {
            "mediaType": "application/vnd.docker.distribution.manifest.v2+json",
            "size": 1375,
            "digest": "sha256:3ecc4d1b70b0c590284d24e6a8738981567bc54896ea03d4aa4a494eeeecc25a",
            "length": 1375,
            "repository": "microsoft",
            "url": "http://localhost:5000/v2/microsoft/manifests/sha256:3ecc4d1b70b0c590284d24e6a8738981567bc54896ea03d4aa4a494eeeecc25a",
            "tag": "latest"
         },
         "request": {
            "id": "6189c2c2-5b57-4970-9538-038b39fb22d2",
            "addr": "172.19.0.1:39304",
            "host": "localhost:5000",
            "method": "PUT",
            "useragent": "docker/18.03.1-ce go/go1.9.5 git-commit/9ee9f40 kernel/4.9.0-6-amd64 os/linux arch/amd64 UpstreamClient(Docker-Client/18.03.1-ce \\(linux\\))"
         },
         "actor": {},
         "source": {
            "addr": "b6203bc638de:5000",
            "instanceID": "375af6b0-42ff-4efd-a8c2-4f4c8b0edb35"
         }
      }
   ]
}

以下是我想要反序列化流的类:

[DataContract]
public class Ev
{
    [DataMember]
    public IList<Event> Events { get; set; }
}

[DataContract]
public class Event
{
    [DataMember]
    public Guid Id { get; set; }
    [DataMember]
    public DateTime Timestamp { get; set; }
    [DataMember]
    public string Action { get; set; }
}

我创建为新 InputFormatter 的反序列化方法

if (contentType == "application/vnd.docker.distribution.events.v1+json")
{
    using (var ms = new MemoryStream(2048))
    {
        await request.Body.CopyToAsync(ms);
        var content = ms.ToArray();
        File.WriteAllBytes("test.txt", content);
        ms.Position = 0;
        try
        {
            DataContractJsonSerializer ser = new DataContractJsonSerializer(typeof(Ev));
            Ev ev = (Ev) ser.ReadObject(ms);
        }
        catch (Exception e)
        {
            Console.WriteLine(e.Message);
        }


        return await InputFormatterResult.SuccessAsync(content);
    }
}

问题是 ev 的事件属性是 null 我想知道为什么。我的反序列化没有正确启动吗?

【问题讨论】:

  • 如果您能提供minimal reproducible example(我们可以复制并粘贴到控制台应用程序)来重现问题,那就太好了。

标签: c# serialization asp.net-core


【解决方案1】:

您可以在 VSCode 中为您的 json 使用扩展名 Paste JSON as Code,这将生成此类文件:

// Generated by https://quicktype.io

namespace QuickType
{
    using System;
    using System.Collections.Generic;

    using System.Globalization;
    using Newtonsoft.Json;
    using Newtonsoft.Json.Converters;

    public partial class TopLevel
    {
        [JsonProperty("events")]
        public Event[] Events { get; set; }
    }

    public partial class Event
    {
        [JsonProperty("id")]
        public string Id { get; set; }

        [JsonProperty("timestamp")]
        public DateTimeOffset Timestamp { get; set; }

        [JsonProperty("action")]
        public string Action { get; set; }

        [JsonProperty("target")]
        public Target Target { get; set; }

        [JsonProperty("request")]
        public Request Request { get; set; }

        [JsonProperty("actor")]
        public Actor Actor { get; set; }

        [JsonProperty("source")]
        public Source Source { get; set; }
    }

    public partial class Actor
    {
    }

    public partial class Request
    {
        [JsonProperty("id")]
        public string Id { get; set; }

        [JsonProperty("addr")]
        public string Addr { get; set; }

        [JsonProperty("host")]
        public string Host { get; set; }

        [JsonProperty("method")]
        public string Method { get; set; }

        [JsonProperty("useragent")]
        public string Useragent { get; set; }
    }

    public partial class Source
    {
        [JsonProperty("addr")]
        public string Addr { get; set; }

        [JsonProperty("instanceID")]
        public string InstanceId { get; set; }
    }

    public partial class Target
    {
        [JsonProperty("mediaType")]
        public string MediaType { get; set; }

        [JsonProperty("size")]
        public long Size { get; set; }

        [JsonProperty("digest")]
        public string Digest { get; set; }

        [JsonProperty("length")]
        public long Length { get; set; }

        [JsonProperty("repository")]
        public string Repository { get; set; }

        [JsonProperty("url")]
        public string Url { get; set; }

        [JsonProperty("tag")]
        public string Tag { get; set; }
    }

    public partial class TopLevel
    {
        public static TopLevel FromJson(string json) => JsonConvert.DeserializeObject<TopLevel>(json, QuickType.Converter.Settings);
    }

    public static class Serialize
    {
        public static string ToJson(this TopLevel self) => JsonConvert.SerializeObject(self, QuickType.Converter.Settings);
    }

    internal static class Converter
    {
        public static readonly JsonSerializerSettings Settings = new JsonSerializerSettings
        {
            MetadataPropertyHandling = MetadataPropertyHandling.Ignore,
            DateParseHandling = DateParseHandling.None,
            Converters = {
                new IsoDateTimeConverter { DateTimeStyles = DateTimeStyles.AssumeUniversal }
            },
        };
    }
}

然后应该使用 Newtonsoft 正确序列化/反序列化。

为了配合DataContractJsonSerializer使用,你可以稍微修改一下得到:

using System;
using System.Collections.Generic;
using System.Globalization;

namespace YourApp
{
    [DataContract]
    public class Ev
    {
        [DataMember(Name = "events")]
        public IList<Event> Events { get; set; }
    }

    [DataContract]
    public class Event
    {
        [DataMember(Name ="id")]
        public string Id { get; set; }

        [DataMember(Name ="timestamp")]
        public DateTimeOffset Timestamp { get; set; }

        [DataMember(Name ="action")]
        public string Action { get; set; }

        [DataMember(Name ="target")]
        public Target Target { get; set; }

        [DataMember(Name ="request")]
        public Request Request { get; set; }

        [DataMember(Name ="actor")]
        public object Actor { get; set; }

        [DataMember(Name ="source")]
        public Source Source { get; set; }
    }

    [DataContract]
    public class Request
    {
        [DataMember(Name ="id")]
        public string Id { get; set; }

        [DataMember(Name = "addr")]
        public string Addr { get; set; }

        [DataMember(Name = "host")]
        public string Host { get; set; }

        [DataMember(Name = "method")]
        public string Method { get; set; }

        [DataMember(Name = "useragent")]
        public string Useragent { get; set; }
    }

    [DataContract]
    public class Source
    {
        [DataMember(Name = "addr")]
        public string Addr { get; set; }

        [DataMember(Name = "instanceID")]
        public string InstanceId { get; set; }
    }

    [DataContract]
    public class Target
    {
        [DataMember(Name = "mediaType")]
        public string MediaType { get; set; }

        [DataMember(Name = "size")]
        public long Size { get; set; }

        [DataMember(Name = "digest")]
        public string Digest { get; set; }

        [DataMember(Name = "length")]
        public long Length { get; set; }

        [DataMember(Name = "repository")]
        public string Repository { get; set; }

        [DataMember(Name = "url")]
        public string Url { get; set; }

        [DataMember(Name = "tag")]
        public string Tag { get; set; }
    }
}

看看那个类是否有效..

【讨论】:

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