有时会导致对象列表或空对象列表的json字符串



我有一个从API返回的JSON字符串,有时是这样,其中"result"键只有一个空对象:

{
  "_meta": {
    "status": "SUCCESS",
    "count": 0
  },
  "result": {}
}

"result"键具有一个对象的数组:

{
  "_meta": {
    "status": "SUCCESS",
    "count": 0
  },
  "result": [
    { ... },
    { ... }
  ]
}

我已经尝试从这个问题中实现自定义JsonConverter,但我想我没有运气。这是我的实现:

class EmptyObjectJsonConverter<T> : JsonConverter
{
    public override bool CanConvert(Type objectType)
    {
        return true;
    }
    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        object retObj = new Object();
        if (reader.TokenType == JsonToken.StartArray)
        {
            retObj = serializer.Deserialize<List<T>>(reader);
        }
        else if (reader.TokenType == JsonToken.StartObject)
        {
            retObj = new List<T>();
        }
        return retObj;
    }
    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        throw new NotImplementedException();
    }
}

我这样使用:

public class ApiReturn
{
    public ApiMeta _Meta { get; set; }
    [JsonConverter(typeof(EmptyObjectJsonConverter<ApiResult>))]
    public List<ApiResult> Result { get; set; }
}

我想从上面的实现中实现的目标是:如果令牌是启动数组,则以正常方式进行对其进行测试,但是如果令牌是启动对象,则只需返回对象的空列表。

但是,当我尝试使用带有空对象的"result"键运行程序时,它会引发异常:Additional text found in JSON string after finishing deserializing object.,而结果ApiReturn.Result为null。

我是否以错误的方式实施它?任何帮助将不胜感激。


update 基于@a。Chiesa答案:请查看我的GetApiResult的实现:

[JsonProperty("result")]
public JToken Result { get; set; }
public T GetResultAs<T>()
{
    var objectReturned = default(T);
    try
    {
        if (Result.Type == JTokenType.Array)
        {
            objectReturned = Result.ToObject<T>();
        }
        else if (Result.Type == JTokenType.Object)
        {
            // Should it return an empty List<ApiResult> if I use type List<ApiResult> ?
            objectReturned = default(T);
        }
    }
    catch
    {
        objectReturned = default(T);
    }
    return objectReturned;
}

当JSON节点令牌是对象时,为什么我会毫无用处?当我使用GetResultAs<List<ApiResult>>时,它应该返回一个空的List<ApiResult>吗?

我喜欢使用JToken属性,该属性由避难所抽象。

真正幼稚的实现将是:

public enum MetaStatus
{
    SUCCESS
    // FAILURE,
    // ... etc
}
public class Meta
{
    public MetaStatus Status { get; set; }
    public long Count { get; set; }
}
public class ApiResponse
{
    [JsonProperty("_meta")]
    public Meta Meta { get; set; }
    [JsonProperty("result")]
    public JToken JsonResult { get; set; }
    public T GetResultAs<T>()
    {
        // put in place some error handling logic, depending upon what's really an error
        // in this method.
        try
        {
            return JsonResult.ToObject<T>();
        }
        catch
        {
            return default(T);
        }
    }
}

简而言之:您要求JSON.NET将结果保留为JSON对象,然后,在执行避免序列化之后,您可以尝试各种方式审理JToken,只需调用类型的GetResultAs,例如GetResultAs<List<ApiLineObj>>()。P>

该代码并不是要使用的(可能要处理一些检查),但是基本的挑选机械师在那里。

您可以立即尝试将JSON验证为对象。我使用JSON2SHARP从您的JSON代码生成类。

public class Meta
{
    public string status { get; set; }
    public int count { get; set; }
}
public class Result
{
    <Add whatever field you are expecting>
}
public class RootObject
{
    public Meta _meta { get; set; }
    public Result result { get; set; }
}

然后,您可以使用下面的行将JSON DESERIALZE到一个对象。

RootObject root = JsonConvert.DeserializeObject<RootObject>("YOUR JSON");

如果结果数组为空,则rootObject类中的列表将为空。

这是我的完整工作实现@a。如果您想知道,Chiesa的答案适合我的需求。

首先,我认为default(T)与创建新实例😂

相同

所以我在这里使用通用类型的实例化(对我来说是新的:C#创建新T()):

public class ApiReturn
{
    [JsonProperty("_meta")]
    public ApiMeta Meta { get; set; }
    [JsonProperty("result")]
    public JToken Result { get; set; }
    public T GetResultAs<T>() where T : new()
    {
        var objectReturned = default(T);
        try
        {
            if (Result.Type == JTokenType.Array)
            {
                objectReturned = Result.ToObject<T>();
            }
            else if (Result.Type == JTokenType.Object)
            {
                objectReturned = new T();
            }
        }
        catch
        {
            objectReturned = new T();
        }
        return objectReturned;
    }
}

相关内容

  • 没有找到相关文章

最新更新