JsonSerialization обычного типа носителя, данные не будут десериализованы - PullRequest
0 голосов
/ 03 июля 2018

Эй, я пытаюсь десериализовать поток json, который какой-то сервис отправляет моей конечной точке. Проблема в том, что эта служба отправляет мне данные с пользовательским типом носителя:

применение / vnd.docker.distribution.manifest.v2 + * JSON 1004 *

E.g поток, который я записываю из памяти, а затем сохраняю в файл:

{
   "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. Мне интересно, почему. Моя десериализация не инициирована должным образом?

1 Ответ

0 голосов
/ 04 июля 2018

Вы можете использовать расширение Вставить JSON в качестве кода в VSCode для вашего json, что сгенерирует этот файл класса:

// 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; }
    }
}

Посмотрите, работает ли этот класс ..

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...