Newtonsoft.Json Serializer与动态和小数的奇怪行为

时间:2015-12-07 17:31:02

标签: c# dynamic casting json.net

我正在尝试将包含小数的动态结构转换为具体类。我无法找到合理的解决方案,因此我使用“hacky”方式将动态结构序列化为JSON,然后将其反序列化为具体类。我的第一个问题是 - 有更好的方法吗?

其实我注意到一些对我来说很奇怪的事情。在做了我刚才解释的事情之后,我试图从这些十进制值中获取字符串值 - a.ToString(CultureInfo.InvariantCulture); 令我惊讶的是,这些字符串不同!一个是10,另一个是10.0。你能解释一下为什么会这样吗?在调试期间,valus似乎都是相同的......

这是我的代码,因此您可以轻松查看:

using System.Globalization;
using Newtonsoft.Json;
using NUnit.Framework;

namespace SimpleFx.UnitTests.UnitTest
{
    public class DecimalStruct
    {
        public DecimalStruct(decimal a)
        {
            A = a;
        }

        public decimal A { get; set; }
    }

    public class DynamicDecimalTest
    {
        /// <summary>
        /// "Hacky" way of casting dynamic object to a concrete class
        /// </summary>
        public static T Convert<T>(dynamic obj) where T : class
        {
            var serialized = JsonConvert.SerializeObject(obj);
            return JsonConvert.DeserializeObject<T>(serialized);
        }

        [Test]
        public void CastTest()
        {
            decimal a = 10;
            dynamic s1 = new DecimalStruct(a);

            var s2 = Convert<DecimalStruct>(s1);

            Assert.AreEqual(a, s1.A);
            Assert.AreEqual(a, s2.A);

            Assert.AreEqual(a.ToString(CultureInfo.InvariantCulture), s1.A.ToString(CultureInfo.InvariantCulture));
            Assert.AreEqual(a.ToString(CultureInfo.InvariantCulture), s2.A.ToString(CultureInfo.InvariantCulture)); // this fails because "10.0" is not equal "10"
        }
    }
}

1 个答案:

答案 0 :(得分:0)

请考虑以下示例将动态转换为具体

    var typeName = "YourNamespace.ExampleObj";

    object obj = new
    {
        A = 5,
        B = "xx"
    };

    var props = TypeDescriptor.GetProperties(obj);
    Type type = Type.GetType(typeName);
    ExampleObj instance = (ExampleObj)Activator.CreateInstance(type);
    instance.A = (int)props["A"].GetValue(obj);
    instance.B = (string)props["B"].GetValue(obj);

//serialize the instance now...