你也可以将你的 JSON 反序列化为目标类的对象,然后像平常一样读取它的属性:
var obj = DeSerializeFromStrToObj<ClassToSerialize>(jsonStr);
Console.WriteLine($"Property: {obj.Property}");
在这里,DeSerializeFromStrToObj
是一个自定义类,利用反射实例化目标类的对象:
public static T DeSerializeFromStrToObj<T>(string json)
{
try
{
var o = (T)Activator.CreateInstance(typeof(T));
try
{
var jsonDict = JsonSerializer.Deserialize<Dictionary<string, string>>(json);
var props = o.GetType().GetProperties();
if (props == null || props.Length == 0)
{
Debug.WriteLine($"Error: properties from target class '{typeof(T)}' could not be read using reflection");
return default;
}
if (jsonDict.Count != props.Length)
{
Debug.WriteLine($"Error: number of json lines ({jsonDict.Count}) should be the same as number of properties ({props.Length})of our class '{typeof(T)}'");
return default;
}
foreach (var prop in props)
{
if (prop == null)
{
Debug.WriteLine($"Error: there was a prop='null' in our target class '{typeof(T)}'");
return default;
}
if (!jsonDict.ContainsKey(prop.Name))
{
Debug.WriteLine($"Error: jsonStr does not refer to target class '{typeof(T)}'");
return default;
}
var value = jsonDict[prop.Name];
Type t = Nullable.GetUnderlyingType(prop.PropertyType) ?? prop.PropertyType;
object safeValue = value ?? Convert.ChangeType(value, t);
prop.SetValue(o, safeValue, null);
}
return o;
}
catch (Exception e2)
{
Debug.WriteLine(e2.Message);
return o;
}
}
catch (Exception e)
{
Debug.WriteLine(e.Message);
return default;
}
}
你可以测试你的 JSON,例如 这里
在这里,你可以找到一个完整的工作示例,其中包含不同的序列化和反序列化方式,这可能对你和/或未来的读者有所帮助:
using System;
using System.Collections.Generic;
using System.Text.Json;
using static Json_Tests.JsonHelpers;
namespace Json_Tests
{
public class Class1
{
public void Test()
{
var obj1 = new ClassToSerialize();
var jsonStr = obj1.ToString();
var obj2 = DeSerializeFromStrToObj<ClassToSerialize>(jsonStr);
Console.WriteLine($"{nameof(obj2.Name)}: {obj2.Name}");
var obj3 = JsonSerializer.Deserialize<object>(jsonStr) as JsonElement?;
var propName = nameof(obj1.Name);
var propVal1 = obj3?.GetProperty("Name");
Console.WriteLine($"{propName}: {propVal1}");
JsonElement propVal2 = default;
obj3?.TryGetProperty("Name", out propVal2);
Console.WriteLine($"{propName}: {propVal2}");
var obj4 = DeSerializeFromStrToDict(jsonStr);
foreach (var pair in obj4)
Console.WriteLine($"{pair.Key}: {pair.Value}");
}
}
[Serializable]
public class ClassToSerialize
{
public string Name { get; } = "Paul";
public string Surname{ get; set; } = "Efford";
public override string ToString() => JsonSerializer.Serialize(this, new JsonSerializerOptions { WriteIndented = true });
}
public static class JsonHelpers
{
public static Dictionary<string, string> DeSerializeFromStrToDict(string json)
{
try
{
return JsonSerializer.Deserialize<Dictionary<string, string>>(json);
}
catch (Exception e)
{
Console.WriteLine(e.Message);
return new Dictionary<string, string>();
}
}
public static T DeSerializeFromStrToObj<T>(string json)
{
try
{
var o = (T)Activator.CreateInstance(typeof(T));
try
{
var jsonDict = JsonSerializer.Deserialize<Dictionary<string, string>>(json);
var props = o.GetType().GetProperties();
if (props == null || props.Length == 0)
{
Console.WriteLine($"Error: properties from target class '{typeof(T)}' could not be read using reflection");
return default;
}
if (jsonDict.Count != props.Length)
{
Console.WriteLine($"Error: number of json lines ({jsonDict.Count}) should be the same as number of properties ({props.Length})of our class '{typeof(T)}'");
return default;
}
foreach (var prop in props)
{
if (prop == null)
{
Console.WriteLine($"Error: there was a prop='null' in our target class '{typeof(T)}'");
return default;
}
if (!jsonDict.ContainsKey(prop.Name))
{
Console.WriteLine($"Error: jsonStr does not refer to target class '{typeof(T)}'");
return default;
}
var value = jsonDict[prop.Name];
Type t = Nullable.GetUnderlyingType(prop.PropertyType) ?? prop.PropertyType;
object safeValue = value ?? Convert.ChangeType(value, t);
prop.SetValue(o, safeValue, null);
}
return o;
}
catch (Exception e2)
{
Console.WriteLine(e2.Message);
return o;
}
}
catch (Exception e)
{
Console.WriteLine(e.Message);
return default;
}
}
}
}