C# 如何使用.net core 3.1中的System.Text.Json获取对象内部的对象值

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

创建了一个.Net Core 3.1Web应用程序,并将请求发布到请求的模型中

public class RequestPayload
    {
        public string MessageName { get; set; }

        public object Payload { get; set; }
    }
我对core 3.1非常陌生,正在努力获取有效负载属性的价值,有人能帮我吗

在找到解决方案的同时,我还比较了NewtonsoftSystem.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);
}