C# 如何使用.net core 3.1中的System.Text.Json获取对象内部的对象值
创建了一个.Net Core 3.1Web应用程序,并将请求发布到请求的模型中C# 如何使用.net core 3.1中的System.Text.Json获取对象内部的对象值,c#,json.net,system.text.json,.net-core-3.1,C#,Json.net,System.text.json,.net Core 3.1,创建了一个.Net Core 3.1Web应用程序,并将请求发布到请求的模型中 public class RequestPayload { public string MessageName { get; set; } public object Payload { get; set; } } 我对core 3.1非常陌生,正在努力获取有效负载属性的价值,有人能帮我吗 在找到解决方案的同时,我还比较了Newtonsoft和System.Text
public class RequestPayload
{
public string MessageName { get; set; }
public object Payload { get; set; }
}
我对core 3.1非常陌生,正在努力获取有效负载属性的价值,有人能帮我吗
在找到解决方案的同时,我还比较了Newtonsoft和System.Text.Json,得到了错误
使用Newtonsoft我可以序列化和反序列化如下所示的模型
public class RequestPayload
{
public string MessageName { get; set; }
public object Payload { get; set; }
//Problem is here -> TYPE
public Type PayloadType { get; set; }
}
但是使用System.Text.Json我不是
序列化时,出现错误“System.Text.Json.JsonException:'检测到不支持的可能的对象循环。”
为了测试反序列化,以某种方式创建了JSON并尝试使用System.Text.JSON对其进行反序列化,但出现错误“System.Text.JSON.JsonException:”JSON值无法转换为System.Type。“
使用了System.Text.Json.JsonSerializer,这是一个问题还是有任何其他可能使其起作用
我对core 3.1非常陌生,正在努力获取有效负载属性的价值,有人能帮我吗
对于System.Object
属性,不同于Newtonsoft.Json
,System.Text.Json
不尝试推断Json负载的类型
以获取基本值(例如true
,12345.67
,“hello”
)。类似地,对于复杂的JSON值,如对象和数组(如{“Name”:“hi”}
或[1,2,3]
),对象属性设置为表示传入JSON的装箱JsonElement
。这类似于复杂类型的Newtonsoft.Json
将JObject
存储到对象属性中的方式。
看
与使用Newtonsoft.Json的JObject
类似,您可以使用JsonElement
遍历和访问Json文档对象模型(DOM)中的值,并在其上调用转换API以获取.NET值(例如GetProperty(String)
和GetInt32()
)
下面的示例显示了在将JSON反序列化为RequestPayload
后,如何访问Payload
值
private static void ObjectPropertyExample()
{
using JsonDocument doc = JsonDocument.Parse("{\"Name\":\"Darshana\"}");
JsonElement payload = doc.RootElement.Clone();
var requestPayload = new RequestPayload
{
MessageName = "message",
Payload = payload
};
string json = JsonSerializer.Serialize(requestPayload);
Console.WriteLine(json);
// {"MessageName":"message","Payload":{"Name":"Darshana"}}
RequestPayload roundtrip = JsonSerializer.Deserialize<RequestPayload>(json);
JsonElement element = (JsonElement)roundtrip.Payload;
string name = element.GetProperty("Name").GetString();
Assert.Equal("Darshana", name);
}
然后可以将自定义转换器添加到选项中,并将其传递给JsonSerializer.Serialize
:
var options = new JsonSerializerOptions();
options.Converters.Add(new CustomJsonConverterForType());
考虑重新评估为什么您需要从序列化和反序列化开始的类上的类型
属性
有关为什么不应使用Type.GetType(string)
反序列化包含Type
属性的类的更多信息和上下文,请参阅
以下是有关如何编写自定义转换器的更多信息:
一种可以更安全地工作的方法(因此我建议使用类型鉴别器枚举),它包含您期望和支持的静态已知类型的列表,并基于JsonConverter
中的枚举值显式创建这些类型
下面是一个这样的例子:
// Let's assume these are the list of types we expect for the `Type` property
public class ExpectedType1 { }
public class ExpectedType2 { }
public class ExpectedType3 { }
public class CustomJsonConverterForType : JsonConverter<Type>
{
public override Type Read(ref Utf8JsonReader reader, Type typeToConvert,
JsonSerializerOptions options)
{
TypeDiscriminator typeDiscriminator = (TypeDiscriminator)reader.GetInt32();
Type type = typeDiscriminator switch
{
TypeDiscriminator.ExpectedType1 => typeof(ExpectedType1),
TypeDiscriminator.ExpectedType2 => typeof(ExpectedType2),
TypeDiscriminator.ExpectedType3 => typeof(ExpectedType3),
_ => throw new NotSupportedException(),
};
return type;
}
public override void Write(Utf8JsonWriter writer, Type value,
JsonSerializerOptions options)
{
if (value == typeof(ExpectedType1))
{
writer.WriteNumberValue((int)TypeDiscriminator.ExpectedType1);
}
else if (value == typeof(ExpectedType2))
{
writer.WriteNumberValue((int)TypeDiscriminator.ExpectedType2);
}
else if (value == typeof(ExpectedType3))
{
writer.WriteNumberValue((int)TypeDiscriminator.ExpectedType3);
}
else
{
throw new NotSupportedException();
}
}
// Used to map supported types to an integer and vice versa.
private enum TypeDiscriminator
{
ExpectedType1 = 1,
ExpectedType2 = 2,
ExpectedType3 = 3,
}
}
private static void TypeConverterExample()
{
var requestPayload = new RequestPayload
{
MessageName = "message",
Payload = "payload",
PayloadType = typeof(ExpectedType1)
};
var options = new JsonSerializerOptions()
{
Converters = { new CustomJsonConverterForType() }
};
string json = JsonSerializer.Serialize(requestPayload, options);
Console.WriteLine(json);
// {"MessageName":"message","Payload":"payload","PayloadType":1}
RequestPayload roundtrip = JsonSerializer.Deserialize<RequestPayload>(json, options);
Assert.Equal(typeof(ExpectedType1), roundtrip.PayloadType);
}
//假设这些是“Type”属性所需的类型列表
公共类应为类型1{}
公共类应为类型2{}
公共类应为类型3{}
公共类CustomJsonConverterForType:JsonConverter
{
公共覆盖类型读取(参考Utf8JsonReader读取器,类型TOCONVERT,
JsonSerializerOptions(可选)
{
TypeDiscriminator TypeDiscriminator=(TypeDiscriminator)reader.GetInt32();
类型=类型鉴别器开关
{
TypeDiscriminator.ExpectedType1=>typeof(ExpectedType1),
TypeDiscriminator.ExpectedType2=>typeof(ExpectedType2),
TypeDiscriminator.ExpectedType3=>typeof(ExpectedType3),
_=>抛出新的NotSupportedException(),
};
返回类型;
}
公共重写无效写入(Utf8JsonWriter,类型值,
JsonSerializerOptions(可选)
{
如果(值==类型(预期类型1))
{
writer.WriteEnumberValue((int)TypeDiscriminator.ExpectedType1);
}
else if(值==类型(预期类型2))
{
writer.WriteEnumberValue((int)TypeDiscriminator.ExpectedType2);
}
else if(值==类型(预期类型3))
{
writer.WriteNumberValue((int)TypeDiscriminator.ExpectedType3);
}
其他的
{
抛出新的NotSupportedException();
}
}
//用于将支持的类型映射为整数,反之亦然。
私有枚举类型鉴别器
{
预期类型1=1,
预期类型2=2,
预期类型3=3,
}
}
私有静态void TypeConverterExample()
{
var requestPayload=新的requestPayload
{
MessageName=“message”,
Payload=“Payload”,
PayloadType=typeof(预期类型1)
};
var options=新的JsonSerializerOptions()
{
转换器={new CustomJsonConverterForType()}
};
string json=JsonSerializer.Serialize(requestPayload,options);
Console.WriteLine(json);
//{“MessageName”:“message”,“Payload”:“Payload”,“PayloadType”:1}
RequestPayload往返=JsonSerializer.Deserialize(json,选项);
Assert.Equal(typeof(ExpectedType1),roundtrip.PayloadType);
}
请提供JSON负载。{“MessageName”:“any”,“payload”:{“Name”:“hi”}或者您要求序列化和非序列化问题?如果是这样,要创建json,我使用newtonsoft序列化并创建json,这是正确的。我的意思是创建json,我创建了RequestPayload类的实例,并设置了类型为type的属性,然后使用newtonsoft序列化创建json。为什么需要<
// Let's assume these are the list of types we expect for the `Type` property
public class ExpectedType1 { }
public class ExpectedType2 { }
public class ExpectedType3 { }
public class CustomJsonConverterForType : JsonConverter<Type>
{
public override Type Read(ref Utf8JsonReader reader, Type typeToConvert,
JsonSerializerOptions options)
{
TypeDiscriminator typeDiscriminator = (TypeDiscriminator)reader.GetInt32();
Type type = typeDiscriminator switch
{
TypeDiscriminator.ExpectedType1 => typeof(ExpectedType1),
TypeDiscriminator.ExpectedType2 => typeof(ExpectedType2),
TypeDiscriminator.ExpectedType3 => typeof(ExpectedType3),
_ => throw new NotSupportedException(),
};
return type;
}
public override void Write(Utf8JsonWriter writer, Type value,
JsonSerializerOptions options)
{
if (value == typeof(ExpectedType1))
{
writer.WriteNumberValue((int)TypeDiscriminator.ExpectedType1);
}
else if (value == typeof(ExpectedType2))
{
writer.WriteNumberValue((int)TypeDiscriminator.ExpectedType2);
}
else if (value == typeof(ExpectedType3))
{
writer.WriteNumberValue((int)TypeDiscriminator.ExpectedType3);
}
else
{
throw new NotSupportedException();
}
}
// Used to map supported types to an integer and vice versa.
private enum TypeDiscriminator
{
ExpectedType1 = 1,
ExpectedType2 = 2,
ExpectedType3 = 3,
}
}
private static void TypeConverterExample()
{
var requestPayload = new RequestPayload
{
MessageName = "message",
Payload = "payload",
PayloadType = typeof(ExpectedType1)
};
var options = new JsonSerializerOptions()
{
Converters = { new CustomJsonConverterForType() }
};
string json = JsonSerializer.Serialize(requestPayload, options);
Console.WriteLine(json);
// {"MessageName":"message","Payload":"payload","PayloadType":1}
RequestPayload roundtrip = JsonSerializer.Deserialize<RequestPayload>(json, options);
Assert.Equal(typeof(ExpectedType1), roundtrip.PayloadType);
}