json 如何将对象类型反序列化回其原始类型?

aiazj4mn  于 2022-12-20  发布在  其他
关注(0)|答案(1)|浏览(144)

我有这样一个类:

public class MyClass
{
    public int Counter { get; set; }
    public string UnderlyingItemString { get; set; }
    public object UnderlyingItem { get; set; }
}

属性UnderlyingItem可以是不同的类型。
如何将其反序列化回原始类型?我确实将UnderlyingItem的对象名存储在UnderlyingItemString
我执行下面的代码来反序列化它,这将UnderlyingItem作为JObject,但我需要它是我创建的自定义类之一。

JsonConvert.DeserializeObject<MyClass>(myJSON);
ulydmbyx

ulydmbyx1#

这里有一个可能的方案,当tested具有gunr2171提到的四种类型时,似乎可以工作,它添加了一个UnderlyingTypeName属性来序列化完整的类型名称,并满足MyClass不能是泛型的要求。
json序列化程序将忽略UnderlyingItem属性本身。此属性的getter将查询加载的程序集,以查找包含目标类型的程序集。如果找到,json反序列化程序将使用特定类型。否则,将调用默认的Json.net反序列化程序。

public class MyClass
{
    public int Counter { get; set; }
    public string UnderlyingItemString { get; set; }
    public string UnderlyingTypeName { get; set; }
    [JsonIgnore]
    public object UnderlyingItem
    {
        get
        {
            if (string.IsNullOrWhiteSpace(UnderlyingItemString))
            {
                return null;
            }
            else
            {
                Type type = typeof(object);
                Assembly assy = null;
                if (!string.IsNullOrEmpty(UnderlyingTypeName))
                    assy =
                        AppDomain
                        .CurrentDomain
                        .GetAssemblies()
                        .FirstOrDefault(_ => _.GetType(UnderlyingTypeName) != null);
                if (assy == null)
                {
                    return JsonConvert.DeserializeObject(UnderlyingItemString);
                }
                else
                {
                    type = assy.GetType(UnderlyingTypeName);
                    return JsonConvert.DeserializeObject(UnderlyingItemString, type);
                }
            }
        }
        set
        {
            if (!Equals(_UnderlyingItem, value))
            {
                _UnderlyingItem = value;
                UnderlyingItemString = JsonConvert.SerializeObject(value);
                UnderlyingTypeName = _UnderlyingItem.GetType().FullName;
            }
        }
    }
    private object _UnderlyingItem = new object();
}

测试台

string[]

MyClass testRoundTripIn, testRoundTripOut;
string json;
Type returnedType;

testRoundTripIn = new MyClass
{
    UnderlyingItem = new string[] { "A", "B", "C"},
};
json = JsonConvert.SerializeObject(testRoundTripIn, Formatting.Indented);

testRoundTripOut = JsonConvert.DeserializeObject<MyClass>(json);

returnedType = testRoundTripOut.UnderlyingItem.GetType();
if (typeof(string[]).Equals(returnedType))
{
    Console.WriteLine($"MyClass.UnderlyingItem deserialized as {returnedType.FullName}");
}
else
{
    Console.WriteLine($"Error string[] Deserialized as {returnedType.Name}");
}

List<string>

testRoundTripIn = new MyClass
{
    UnderlyingItem = new List<string> { "A", "B", "C"},
};
json = JsonConvert.SerializeObject(testRoundTripIn, Formatting.Indented);

testRoundTripOut = JsonConvert.DeserializeObject<MyClass>(json);

returnedType = testRoundTripOut.UnderlyingItem.GetType();
if (typeof(List<string>).Equals(returnedType))
{
    Console.WriteLine($"MyClass.UnderlyingItem deserialized as {returnedType.Name}");
}
else
{
    Console.WriteLine($"Error List<string> deserialized as {returnedType.FullName}");
}

double

testRoundTripIn = new MyClass
{
    UnderlyingItem = Math.PI,
};
json = JsonConvert.SerializeObject(testRoundTripIn, Formatting.Indented);

testRoundTripOut = JsonConvert.DeserializeObject<MyClass>(json);

returnedType = testRoundTripOut.UnderlyingItem.GetType();
if (typeof(double).Equals(returnedType))
{
    Console.WriteLine($"MyClass.UnderlyingItem deserialized as {returnedType.Name}");
}
else
{
    Console.WriteLine($"Error double deserialized as {returnedType.FullName}");
}

decimal

testRoundTripIn = new MyClass
{
    UnderlyingItem = 1.23m,
};
json = JsonConvert.SerializeObject(testRoundTripIn, Formatting.Indented);

testRoundTripOut = JsonConvert.DeserializeObject<MyClass>(json);

returnedType = testRoundTripOut.UnderlyingItem.GetType();
if (typeof(decimal).Equals(returnedType))
{
    Console.WriteLine($"MyClass.UnderlyingItem deserialized as {returnedType.Name}");
}
else
{
    Console.WriteLine($"Error decimal deserialized as {returnedType.FullName}");
}

相关问题