【问题标题】:Use another property from json in a custom JsonConverter在自定义 JsonConverter 中使用来自 json 的另一个属性
【发布时间】:2020-09-05 21:30:42
【问题描述】:

假设以下 JSON:

{
  "channel": "751853588527054938"
  "message": "751853745758928908"
}

还有以下部分代码:

        [JsonConverter(typeof(TextChannelConverter))]
        [JsonProperty("channel")]
        public ITextChannel Channel;

        [JsonConverter(typeof(UserMessageConverter))]
        [JsonProperty("message")]
        public IUserMessage Message;

我想要做的是,我想为这两种类型的去实现一个自定义转换器,但问题是,如果我只有它的 ID,我无法收到消息,我还需要知道这样做的通道 ID(更准确地说,使用 ITextChannel#GetMessageAsync(ulong id) 检索消息)。有没有办法在 UserMessageConverter 中访问通道的 ID 甚至通道对象?

我已经尝试从阅读器加载整个 JSON

    class UserMessageConverter : JsonConverter
    {
        public override bool CanWrite => false;
        public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) => throw new NotImplementedException();

        public override bool CanConvert(Type objectType) => objectType == typeof(IUserMessage);

        public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
        {
            JObject jobj = JObject.Load(reader);
            return null;
        }

但它发出一个异常:

Newtonsoft.Json.JsonReaderException: Error reading JObject from JsonReader. Current JsonReader item is not an object: Integer. Path 'message', line 1, position 75.

TextChannelConverter的代码供参考:

        class TextChannelConverter : JsonConverter
        {
        public override bool CanWrite => false;
        public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) => throw new NotImplementedException();

        public override bool CanConvert(Type objectType) => objectType == typeof(ITextChannel);

        public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
        {
            if (reader.Value == null)
                return null;

            ulong channelid = ulong.Parse(reader.Value.ToString());

            return Essentials.FireLands.GetChannel(channelid);
        }

【问题讨论】:

  • 这似乎是一种使用JsonConverter 的奇怪方式。你为什么不只是反序列化为字符串,这就是它......然后在反序列化处理数据之后。看起来你正试图用 1 块石头杀死 2 只鸟……但为什么呢?您可能需要在 ReadJson 中执行 I/O 绑定操作,而 ReadJson 不是异步的,因此会阻塞。

标签: c# json json.net deserialization


【解决方案1】:

如果其中一个属性依赖于另一个,那么您需要创建一个处理父对象的JsonConverter,而不是为每个子属性创建两个单独的转换器。

您没有说明模型中哪个类包含 ChannelMessage 属性,因此我将其称为 Chat 以作为示例。

所以你会:

[JsonConverter(typeof(ChatConverter))]
class Chat
{    
    public ITextChannel Channel { get; set; }
    public IUserMessage Message { get; set; }
}

然后你的转换器可能看起来像这样:

class ChatConverter : JsonConverter
{
    public override bool CanConvert(Type objectType) => objectType == typeof(Chat);
    public override bool CanWrite => false;
    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) => throw new NotImplementedException();

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        if (reader.Value == null)
            return null;

        JObject obj = JObject.Load(reader);
        ulong channelId = (ulong)obj["channel"];
        ulong messageId = (ulong)obj["message"];

        ITextChannel channel = Essentials.FireLands.GetChannel(channelId);
        IUserMessage = channel.GetMessageAsync(messageId).Result;

        return new Chat { Channel = channel, Message = message };
    }
}

【讨论】:

    猜你喜欢
    • 2017-09-08
    • 1970-01-01
    • 2020-01-22
    • 1970-01-01
    • 2019-08-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-07-06
    相关资源
    最近更新 更多