我有一个从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;
}
}