C# 将 Json 字符串 属性 转换为 T 泛型
C# convert Json string property to T generic type
我有一个 class 类型,其中包含字符串 属性 名称和 T 属性 值。我收到一个具有不同属性的 Json 对象,其中两个是名称和值。
我正在通过反射创建类型(在示例中我明确创建了一个布尔值)并且我需要将接收到的字符串值分配给可以是任何类型的 Type.Value 属性。
我该怎么做?类型可以是 int string、List(任何已知类型)或我创建的新类型。我不想切换接收到的字符串类型名称来创建特定的值类型。
我想要一种通用的方法来避免每次在我的系统中创建新类型时都更新此方法。如果我使用反射创建类型 class 实例,我还想在不知道类型的情况下在运行时更新值 属性。
我的代码不处理反序列化(这发生在我无权访问的其他代码中。即使使用 acess,进行反序列化的项目也无法识别自定义类型因为它是一个common/util项目。所以在这种情况下,我只需要关注将字符串值转换为T值。
public class Type<T>
{
public string Name { get; set; }
public Type Type => typeof(T)
public T Value { get; set; }
}
public MyResultObject
{
public string ReqId { get; set; }
public string Name { get; set; }
public string Value { get; set; }
}
var jsonResult = myResultObject //type of MyResultObject
var type = new type<bool>(); //in my code this is created with reflection
type.Name = jsonResult.Name;
type.Value = jsonResult.Value as bool ??? //I want to convert the string Value to the explicit type that can be any T type
最佳方法取决于您未包含的详细信息。
如果您不知道反序列化时的类型,但您在代码的稍后时间知道类型,一种解决方案可能是将值 属性 保留为一个 JToken,然后当你的代码知道它需要什么类型时转换它:
public MyResultObject
{
public string ReqId { get; set; }
public string Name { get; set; }
public JToken Value { get; set; }
}
type.Value = jsonResult.Value<bool>(); // or .Value<T>()
如果您需要将对象反序列化为正确的具体类型,但您在编译时不知道该类型可能是什么,JSON.NET 有一个内置功能来处理此问题:TypeNameHandling。如果您使用像这样的序列化程序选项序列化和反序列化您的对象:
new JsonSerializerSettings
{
TypeNameHandling = TypeNameHandling.Auto
}
... 然后你可以让你的 Value
属性 成为 object
并且 JSON.NET 会自动将类型元数据添加到序列化对象中,以便它可以被序列化到正确的类型。
不过,这种方法有两个潜在的缺点。一是您必须同时控制序列化和反序列化。另一个是,如果您不信任的人提供 JSON,则可能存在安全隐患:他们可能会实例化一些您不希望他们能够创建的随机对象类型。
有一种折中方法,您可以使用自定义类型转换器根据 JSON 对象上其他内容的值来确定要创建的对象类型,但您可以更好地控制哪些类型可能创建的对象,以及如何在 JSON.
中表示
您的样本没有很好地说明问题。如果您知道 Type<T>
的 <T>
,只需在 Type<T>
class 上添加一个方法,通过 JsonConvert
从 NewtonsoftJson
或 [=16] 进行解析=] 来自 System.Text.Json
,问题将得到解决。我在这里遗漏了什么吗?
public class Type<T>
{
public string Name { get; set; }
public Type GenericType => typeof(T);
public T Value { get; set; }
public void SetValueFromString(string value)
{
Value = JsonConvert.DeserializeObject<T>(value);
}
}
我有一个 class 类型,其中包含字符串 属性 名称和 T 属性 值。我收到一个具有不同属性的 Json 对象,其中两个是名称和值。
我正在通过反射创建类型(在示例中我明确创建了一个布尔值)并且我需要将接收到的字符串值分配给可以是任何类型的 Type.Value 属性。
我该怎么做?类型可以是 int string、List(任何已知类型)或我创建的新类型。我不想切换接收到的字符串类型名称来创建特定的值类型。 我想要一种通用的方法来避免每次在我的系统中创建新类型时都更新此方法。如果我使用反射创建类型 class 实例,我还想在不知道类型的情况下在运行时更新值 属性。
我的代码不处理反序列化(这发生在我无权访问的其他代码中。即使使用 acess,进行反序列化的项目也无法识别自定义类型因为它是一个common/util项目。所以在这种情况下,我只需要关注将字符串值转换为T值。
public class Type<T>
{
public string Name { get; set; }
public Type Type => typeof(T)
public T Value { get; set; }
}
public MyResultObject
{
public string ReqId { get; set; }
public string Name { get; set; }
public string Value { get; set; }
}
var jsonResult = myResultObject //type of MyResultObject
var type = new type<bool>(); //in my code this is created with reflection
type.Name = jsonResult.Name;
type.Value = jsonResult.Value as bool ??? //I want to convert the string Value to the explicit type that can be any T type
最佳方法取决于您未包含的详细信息。
如果您不知道反序列化时的类型,但您在代码的稍后时间知道类型,一种解决方案可能是将值 属性 保留为一个 JToken,然后当你的代码知道它需要什么类型时转换它:
public MyResultObject
{
public string ReqId { get; set; }
public string Name { get; set; }
public JToken Value { get; set; }
}
type.Value = jsonResult.Value<bool>(); // or .Value<T>()
如果您需要将对象反序列化为正确的具体类型,但您在编译时不知道该类型可能是什么,JSON.NET 有一个内置功能来处理此问题:TypeNameHandling。如果您使用像这样的序列化程序选项序列化和反序列化您的对象:
new JsonSerializerSettings
{
TypeNameHandling = TypeNameHandling.Auto
}
... 然后你可以让你的 Value
属性 成为 object
并且 JSON.NET 会自动将类型元数据添加到序列化对象中,以便它可以被序列化到正确的类型。
不过,这种方法有两个潜在的缺点。一是您必须同时控制序列化和反序列化。另一个是,如果您不信任的人提供 JSON,则可能存在安全隐患:他们可能会实例化一些您不希望他们能够创建的随机对象类型。
有一种折中方法,您可以使用自定义类型转换器根据 JSON 对象上其他内容的值来确定要创建的对象类型,但您可以更好地控制哪些类型可能创建的对象,以及如何在 JSON.
中表示您的样本没有很好地说明问题。如果您知道 Type<T>
的 <T>
,只需在 Type<T>
class 上添加一个方法,通过 JsonConvert
从 NewtonsoftJson
或 [=16] 进行解析=] 来自 System.Text.Json
,问题将得到解决。我在这里遗漏了什么吗?
public class Type<T>
{
public string Name { get; set; }
public Type GenericType => typeof(T);
public T Value { get; set; }
public void SetValueFromString(string value)
{
Value = JsonConvert.DeserializeObject<T>(value);
}
}