C#Newtonsoft.Json.Linq.JValue总是返回Int64 [英] C# Newtonsoft.Json.Linq.JValue always returning Int64

查看:1979
本文介绍了C#Newtonsoft.Json.Linq.JValue总是返回Int64的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用Newtonsoft.Json程序集将Json字符串序列化为动态对象(ExpandoObject)。我遇到的问题是int值总是作为Int64返回,我期望Int32。代码可以在下面看到。

I am using the Newtonsoft.Json assembly to de-serialize a Json string into a dynamic object (ExpandoObject). The problem I am having is the int value is always returned as an Int64 where I am expecting an Int32. The code can be seen below.

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被用于反思一些类型检查,并且它失败了。

Normally I wouldn't notice this but this particular int is being used in reflection for some type checking and it fails miserably. Any ideas why this is happening would be greatly appreciated.

推荐答案

交叉链接以回答 https://stackoverflow.com/a/9444519/1037948

如何更改数字反序列化的默认类型?

释义:


  • 作者有意地选择所有的int返回为$ code> Int64 以避免溢出错误,更容易检查(对于Json.NET内部组件而不是您)

  • 您可以使用自定义转换器像链接的答案中的一个。

  • The author intentionally chose that all int's come back as Int64 to avoid overflow errors, and it's easier to check (for Json.NET internals, not you)
  • You can get around this with a custom converter like the one posted in the linked answer.

这是一个非常通用的转换器;不完全确定 CanConvert 检查,但对我有用的重要部分是允许 typeof(object)

Here's a really generic converter; not entirely sure about the CanConvert check, but the important part that worked for me was allowing 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) ||
                objectType == typeof(int) ||
                // 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的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆