gpt4 book ai didi

c# - 我可以创建一个仅包含对象类型的空值的 JSON 示例吗?

转载 作者:太空宇宙 更新时间:2023-11-03 11:59:02 24 4
gpt4 key购买 nike

我们正在使用 webhook 和事件做一些事情。我想创建一个基于发送到 webhook 的事件类型的 JSON 负载示例。

假设我有这样一个类:

public class TestClass{
public int Id {get;set;}
}

现在我想要的是能够创建类似的东西

{
"id": 0
}

仅通过了解 typeof(TestClass)

我不想创建我的对象的实例,因为其中一些相当复杂并且有各种参数要求。

我只想要一个不包含任何值的 JSON 表示。

有什么想法吗?

最佳答案

您可以使用 Json.NET 的 contract resolver类获得JsonContract对于您希望序列化的类型。协定定义 Json.NET 如何序列化类型,因此可用于生成默认表示。

原型(prototype)实现可能如下所示:

public static partial class JsonExtensions
{
readonly static IContractResolver defaultResolver = new JsonSerializer().ContractResolver;

public static string WriteDefaultValuesForTypeToString(Type type, IContractResolver resolver = null, Formatting formatting = Formatting.None)
{
using (var sw = new StringWriter())
{
using (var jsonWriter = new JsonTextWriter(sw) { Formatting = formatting })
{
WriteDefaultValuesForType(type, jsonWriter, resolver);
}
return sw.ToString();
}
}

public static void WriteDefaultValuesForType(Type type, JsonWriter writer, IContractResolver resolver = null)
{
var serializer = JsonSerializer.Create(new JsonSerializerSettings{ ContractResolver = resolver });
WriteDefaultValuesForType(type, writer, serializer, null, 0);
}

static void WriteDefaultValuesForType(Type type, JsonWriter writer, JsonSerializer serializer, JsonProperty parent, int depth)
{
var contract = serializer.ContractResolver.ResolveContract(type);
var defaultValue = parent?.DefaultValue;
if (defaultValue == null && type.IsValueType && Nullable.GetUnderlyingType(type) == null)
{
defaultValue = contract.DefaultCreator();
}

if (contract is JsonPrimitiveContract primitive)
{
serializer.Serialize(writer, defaultValue);
}
else if (contract is JsonObjectContract obj)
{
if (depth > 0 && defaultValue == null)
{
writer.WriteNull();
}
else
{
writer.WriteStartObject();

foreach (var p in obj.Properties)
{
writer.WritePropertyName(p.PropertyName);
WriteDefaultValuesForType(p.PropertyType, writer, serializer, p, depth++);
}

writer.WriteEndObject();
}
}
else if (contract is JsonArrayContract array)
{
writer.WriteStartArray();
writer.WriteEndArray();
}
else if (contract is JsonDictionaryContract dict)
{
if (depth > 0 && defaultValue == null)
{
writer.WriteNull();
}
else
{
writer.WriteStartObject();
writer.WriteEndObject();
}
}
else if (contract is Newtonsoft.Json.Serialization.JsonLinqContract linq)
{
/* What to do here? */
writer.WriteNull();
}
else
{
//JsonISerializableContract, JsonDynamicContract,
throw new JsonSerializationException(string.Format("Unsupported contract {0}", contract));
}
}
}

然后,您可以为 TestClass 生成一个默认的 JSON,如下所示:

var defaultJson = JsonExtensions.WriteDefaultValuesForTypeToString(typeof(TestClass), formatting : Formatting.Indented);

注意事项:

  • 不寻常的契约(Contract),例如 JsonDynamicContractJsonISerializableContract尚未实现。

  • 如果 custom JsonConverter一直applied对于类型,没有直接的方法来生成默认序列化而不调用 WriteJson()并传入该类型的实例。

    可能能够使用FormatterServices.GetUninitializedObject(Type)在不调用构造函数的情况下生成您的类型的空实例,然后将其传递给 WriteJson() 以生成默认序列化。不能保证这会起作用。如果转换器希望通过正确调用构造函数来初始化集合等成员,则可能会抛出异常。

  • 同样,无法为实现 ISerializable 的类型生成默认序列化。没有实例。

  • 如果您使用驼峰式大小写,则可以为 resolver 参数传递 new CamelCasePropertyNamesContractResolver()

  • 在嵌套复杂对象的情况下,WriteDefaultValuesForType() 可以递归,但是在递归数据模型的情况下,您需要注意不要溢出堆栈。

  • 作为替代方法,您可以考虑生成并使用 在你的应用程序中。参见例如Generating Schemas .

演示 fiddle here .

关于c# - 我可以创建一个仅包含对象类型的空值的 JSON 示例吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57957797/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com