C#Newtonsoft.Json.Linq.JValue始终返回Int64
我正在使用Newtonsoft.Json程序集将Json字符串反序列化为动态对象(ExpandoObject)。我遇到的问题是int值始终以我期望的Int32形式返回为Int64。该代码可以在下面看到。
namespace Serialization{
using System;
using System.Collections.Generic;
using System.Dynamic;
using System.Linq;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
public static class JsonSerializer
{
#region Public Methods
public static string Serialize(dynamic obj)
{
return JsonConvert.SerializeObject(obj);
}
public static dynamic Deserialize(string s)
{
var obj = JsonConvert.DeserializeObject(s);
return obj is string ? obj as string : Deserialize((JToken)obj);
}
#endregion
#region Methods
private static dynamic Deserialize(JToken token)
{
// FROM : http://blog.petegoo.com/archive/2009/10/27/using-json.net-to-eval-json-into-a-dynamic-variable-in.aspx
// Ideally in the future Json.Net will support dynamic and this can be eliminated.
if (token is JValue) return ((JValue)token).Value;
if (token is JObject)
{
var expando = new ExpandoObject();
(from childToken in token
where childToken is JProperty
select childToken as JProperty).ToList().
ForEach(property => ((IDictionary<string, object>)expando).Add(property.Name, Deserialize(property.Value)));
return expando;
}
if (token is JArray)
{
var items = new List<object>();
foreach (var arrayItem in ((JArray)token)) items.Add(Deserialize(arrayItem));
return items;
}
throw new ArgumentException(string.Format("Unknown token type '{0}'", token.GetType()), "token");
}
#endregion
}
}
通常我不会注意到这一点,但是这个特殊的int被用于某种类型检查的反映,并且失败了。任何想法为什么会发生这种情况将不胜感激。
回答:
释义:
- 作者有意选择将所有int都返回,
Int64
以避免溢出错误,并且检查起来更容易(对于Json.NET内部而言,不是您自己) - 您可以使用自定义转换器(如链接答案中发布的转换器)来解决此问题。
这是一个真正的通用转换器;不能完全确定CanConvert
支票,但对我有用的重要部分是允许typeof(object)
:
/// <summary>/// To address issues with automatic Int64 deserialization -- see https://stackoverflow.com/a/9444519/1037948
/// </summary>
public class JsonInt32Converter : JsonConverter
{
#region Overrides of JsonConverter
/// <summary>
/// Only want to deserialize
/// </summary>
public override bool CanWrite { get { return false; } }
/// <summary>
/// Placeholder for inheritance -- not called because <see cref="CanWrite"/> returns false
/// </summary>
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
// since CanWrite returns false, we don't need to implement this
throw new NotImplementedException();
}
/// <summary>
/// Reads the JSON representation of the object.
/// </summary>
/// <param name="reader">The <see cref="T:Newtonsoft.Json.JsonReader"/> to read from.</param><param name="objectType">Type of the object.</param><param name="existingValue">The existing value of object being read.</param><param name="serializer">The calling serializer.</param>
/// <returns>
/// The object value.
/// </returns>
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
return (reader.TokenType == JsonToken.Integer)
? Convert.ToInt32(reader.Value) // convert to Int32 instead of Int64
: serializer.Deserialize(reader); // default to regular deserialization
}
/// <summary>
/// Determines whether this instance can convert the specified object type.
/// </summary>
/// <param name="objectType">Type of the object.</param>
/// <returns>
/// <c>true</c> if this instance can convert the specified object type; otherwise, <c>false</c>.
/// </returns>
public override bool CanConvert(Type objectType)
{
return objectType == typeof(Int32) ||
objectType == typeof(Int64) ||
// need this last one in case we "weren't given" the type
// and this will be accounted for by `ReadJson` checking tokentype
objectType == typeof(object)
;
}
#endregion
}
以上是 C#Newtonsoft.Json.Linq.JValue始终返回Int64 的全部内容, 来源链接: utcz.com/qa/401818.html