我有一个从API返回的JSON字符串,有时候这样,"result"
键只有一个空对象:
{
"_meta": {
"status": "SUCCESS",
"count": 0
},
"result": {}
}
或者这个,其中"result"
键有一个对象数组:
{
"_meta": {
"status": "SUCCESS",
"count": 0
},
"result": [
{ ... },
{ ... }
]
}
我已尝试从此question实施自定义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; }
}
我想从上面的实现中实现的是:如果令牌是start数组,那么以正常方式反序列化它,但如果令牌是起始对象,那么只返回一个空的对象列表。
但是,当我尝试使用具有空对象的"result"
键运行程序时,它会引发异常:Additional text found in JSON string after finishing deserializing object.
,结果ApiReturn.Result
为空。
我是以错误的方式实施的吗?任何帮助将不胜感激。
基于@A的 更新。基耶萨回答:请查看我对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节点令牌是对象时我得到null?当我使用List<ApiResult>
时,它应该返回空GetResultAs<List<ApiResult>>
吗?
答案 0 :(得分:1)
我喜欢使用由反序列化类抽象的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
,只需调用一个类型{{1和} GetResultAs
一样。
代码不是按原样使用(可能你想要处理一些检查),但基本的反序列化机制就在那里。
答案 1 :(得分:0)
您可以尝试立即将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反序列化为对象。
RootObject root = JsonConvert.DeserializeObject<RootObject>("YOUR JSON");
如果结果数组为空,则RootObject类中的列表将为空。
答案 2 :(得分:0)
这是我对@A的全面实施。如果你想知道的话,基耶萨的答案符合我的需要。
起初我认为default(T)
与创建新实例相同
所以在这里我使用泛型类型的实例化(对我来说是新的:C# Create New 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;
}
}