首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >如何使用JSON.net处理同一属性的单个项和数组

如何使用JSON.net处理同一属性的单个项和数组
EN

Stack Overflow用户
提问于 2013-09-25 09:18:57
回答 4查看 47.8K关注 0票数 122

我正在尝试修复我的SendGridPlus库来处理SendGrid事件,但我遇到了一些问题,因为在API中对类别的处理不一致。

在下面的示例中,您将注意到每个项目的category属性既可以是单个字符串,也可以是字符串数组。

代码语言:javascript
复制
[
  {
    "email": "john.doe@sendgrid.com",
    "timestamp": 1337966815,
    "category": [
      "newuser",
      "transactional"
    ],
    "event": "open"
  },
  {
    "email": "jane.doe@sendgrid.com",
    "timestamp": 1337966815,
    "category": "olduser",
    "event": "open"
  }
]

似乎我的选择是在字符串到来之前修复字符串,或者配置JSON.NET以接受不正确的数据。如果我能逃脱惩罚,我宁愿不做任何字符串解析。

有没有其他方法可以使用Json.Net来处理这个问题?

EN

回答 4

Stack Overflow用户

发布于 2015-09-17 19:15:55

我为此工作了很长时间,感谢Brian的回答。我要添加的是vb.net答案!:

代码语言:javascript
复制
Public Class SingleValueArrayConverter(Of T)
sometimes-array-and-sometimes-object
    Inherits JsonConverter
    Public Overrides Sub WriteJson(writer As JsonWriter, value As Object, serializer As JsonSerializer)
        Throw New NotImplementedException()
    End Sub

    Public Overrides Function ReadJson(reader As JsonReader, objectType As Type, existingValue As Object, serializer As JsonSerializer) As Object
        Dim retVal As Object = New [Object]()
        If reader.TokenType = JsonToken.StartObject Then
            Dim instance As T = DirectCast(serializer.Deserialize(reader, GetType(T)), T)
            retVal = New List(Of T)() From { _
                instance _
            }
        ElseIf reader.TokenType = JsonToken.StartArray Then
            retVal = serializer.Deserialize(reader, objectType)
        End If
        Return retVal
    End Function
    Public Overrides Function CanConvert(objectType As Type) As Boolean
        Return False
    End Function
End Class

然后在你的班上:

代码语言:javascript
复制
 <JsonProperty(PropertyName:="JsonName)> _
 <JsonConverter(GetType(SingleValueArrayConverter(Of YourObject)))> _
    Public Property YourLocalName As List(Of YourObject)

希望这能节省你的时间

票数 7
EN

Stack Overflow用户

发布于 2021-11-19 19:32:53

我只是想在上面的SingleOrArrayCollectionConverter上给@dbc添加一个很好的回应。我能够将其修改为与来自HTTP客户端的流一起使用。下面是一个代码片段(您必须设置requestUrl (字符串)和httpClient (使用System.Net.Http;)。

代码语言:javascript
复制
public async Task<IList<T>> HttpRequest<T>(HttpClient httpClient, string requestedUrl, CancellationToken cancellationToken)
    {
       using (var request = new HttpRequestMessage(HttpMethod.Get, requestedUrl))
       using (var httpResponseMessage = await httpClient.SendAsync(request, HttpCompletionOption.ResponseHeadersRead, cancellationToken))
       {
          if (httpResponseMessage.IsSuccessStatusCode)
          {
             using var stream = await httpResponseMessage.Content.ReadAsStreamAsync();    
             using var streamReader = new StreamReader(stream);
             using var jsonTextReader = new JsonTextReader(streamReader );
             var settings = new JsonSerializerSettings
             {
                // Pass true if you want single-item lists to be reserialized as single items
                Converters = { new SingleOrArrayCollectionConverter(true) },
             };
             var jsonSerializer = JsonSerializer.Create(settings);
             return jsonSerializer.Deserialize<List<T>>(jsonTextReader);
     }

如果有丢失的括号或拼写错误,我很抱歉,在这里粘贴代码并不容易。

票数 1
EN

Stack Overflow用户

发布于 2013-09-25 09:30:15

您可以使用此处提供的JSONConverterAttributehttp://james.newtonking.com/projects/json/help/

假设您有一个类,如下所示

代码语言:javascript
复制
public class RootObject
{
    public string email { get; set; }
    public int timestamp { get; set; }
    public string smtpid { get; set; }
    public string @event { get; set; }
    public string category[] { get; set; }
}

您将装饰类别属性,如下所示:

代码语言:javascript
复制
    [JsonConverter(typeof(SendGridCategoryConverter))]
    public string category { get; set; }

public class SendGridCategoryConverter : JsonConverter
{
  public override bool CanConvert(Type objectType)
  {
    return true; // add your own logic
  }

  public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
  {
   // do work here to handle returning the array regardless of the number of objects in 
  }

  public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
  {
    // Left as an exercise to the reader :)
    throw new NotImplementedException();
  }
}
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/18994685

复制
相关文章

相似问题

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