C# 反序列化具有混合值System.Text.JSON的JSON数组
我正在尝试创建一个在.NETCore3.1中呈现的页面,它呈现基于JSON的页面 在这篇文章的结尾,我怎样才能真正地对JSON进行序列化呢 我尝试过反序列化它,但是它不起作用,因为我丢失了每个组件的数据, 因为Page类有一个C# 反序列化具有混合值System.Text.JSON的JSON数组,c#,json,inheritance,system.text.json,C#,Json,Inheritance,System.text.json,我正在尝试创建一个在.NETCore3.1中呈现的页面,它呈现基于JSON的页面 在这篇文章的结尾,我怎样才能真正地对JSON进行序列化呢 我尝试过反序列化它,但是它不起作用,因为我丢失了每个组件的数据, 因为Page类有一个列表——但我需要它是一个不同组件的列表 页面模型: public class Page { public int id { get; set; } public string pagename { get; set; }
列表
——但我需要它是一个不同组件的列表
页面模型:
public class Page
{
public int id { get; set; }
public string pagename { get; set; }
public string metatitle { get; set; }
public string metadescription { get; set; }
public string created_at { get; set; }
public string updated_at { get; set; }
public List<Component> components { get; set; }
}
public class Pages
{
public List<Page> pages { get; set; }
}
一个组成部分:
public class Title : Component
{
public string component { get; set; }
public int id { get; set; {
public string titletext { get; set; }
}
这是JSON:
{
"id":1,
"pagename":"home",
"metatitle":"no title",
"metadescription":"no meta",
"created_at":"2020-05-31T16:35:52.084Z",
"updated_at":"2020-05-31T16:35:52.084Z",
"components":[
{
"component":"components.titletext",
"id":1,
"titletext":"hello"
},
{
"component":"components.section",
"id":2,
"titletext":"hello",
"descriptiontext":"its a beatiful day in lost santos",
"buttonlink":"/go"
},
{
"component":"components.cta",
"id":3,
"sectiontitle":"hello",
"buttonlink":"/go",
"buttontext":"click me"
}
]
}
如果不希望像这样将所有属性添加到
组件
类:
public class Component
{
public string component { get; set; }
public int id { get; set; }
public string titletext { get; set; }
public string sectiontitle { get; set; }
public string buttonlink { get; set; }
public string descriptiontext { get; set; }
}
例如,您需要编写自定义代码(不是很好的实现,但可以使用json,您不需要手动解析每个字段):
公共类ComponentConverter:JsonConverter
{
公共覆盖组件读取(参考Utf8JsonReader reader,类型为typeToConvert,JsonSerializerOptions选项)
{
使用(var doc=JsonDocument.ParseValue(ref reader))
{
var type=doc.RootElement.GetProperty(@“组件”).GetString();
开关(类型)
{
案例“components.titletext”:
返回JsonSerializer.Deserialize(doc.RootElement.GetRawText());
//其他类型处理
默认值:返回JsonSerializer.Deserialize(doc.RootElement.GetRawText());
}
}
}
公共重写无效写入(Utf8JsonWriter编写器、组件值、JsonSerializerOptions选项)
{
抛出新的NotImplementedException();
}
}
公共类组件
{
公共字符串组件{get;set;}
公共int id{get;set;}
}
公共类标题:组件
{
公共字符串titletext{get;set;}
}
和使用示例:
var json = @"[
{
""component"":""components.titletext"",
""id"":1,
""titletext"":""hello""
},
{
""component"":""components.section"",
""id"":2,
""titletext"":""hello"",
""descriptiontext"":""its a beatiful day in lost santos"",
""buttonlink"":""/go""
},
{
""component"":""components.cta"",
""id"":3,
""sectiontitle"":""hello"",
""buttonlink"":""/go"",
""buttontext"":""click me""
}
]";
var deserializeOptions = new JsonSerializerOptions();
deserializeOptions.Converters.Add(new ComponentConverter());
JsonSerializer.Deserialize<List<Component>>(json, deserializeOptions).Dump();
var json=@”[
{
“组件”:“组件.标题文本”,
“id”:1,
“标题文字”:“您好”
},
{
“”组件“”:“”组件。节“”,
“id”:2,
“titletext”:“你好”,
“这是在迷失的桑托斯度过的美好的一天”,
“按钮链接”:“/go”
},
{
“组件”:“组件.cta”,
“id”:3,
“sectiontitle”:“你好”,
“按钮链接”:“/go”,
“按钮文本”:“单击我”
}
]";
var deserializeOptions=新的JsonSerializerOptions();
反序列化options.Converters.Add(newcomponentconverter());
反序列化(json,反序列化选项).Dump();
也不要将此转换器用作
JSONConverterateAttribute
的参数,因为它将以stackoverflow结束。如果您想要/需要完全独立的无关类,可以使用不使用转换器的技术:
var ays = new List<A>();
var bees = new List<B>();
using var doc = JsonDocument.Parse(json);
foreach (var block in doc.RootElement.EnumerateArray())
{
switch (block.GetProperty("component").GetString())
{
case "typeA": ays.Add(Deserialise<A>(block)); break;
case "typeB": bees.Add(Deserialise<B>(block)); break;
// ... case
//default: ...
}
}
var composite = new
{
As = ays,
Bs = bees
};
// This is OK, but if you need to speed it up, please have a look at
// https://stackoverflow.com/questions/58138793/system-text-json-jsonelement-toobject-workaround
static T Deserialise<T>(JsonElement e) => JsonSerializer.Deserialize<T>(e.GetRawText(), options: new JsonSerializerOptions { PropertyNameCaseInsensitive = true });
var=newlist();
var=newlist();
使用var doc=JsonDocument.Parse(json);
foreach(doc.RootElement.EnumerateArray()中的变量块)
{
开关(block.GetProperty(“组件”).GetString()
{
案例“typeA”:ays.Add(反序列化(块));break;
案例“typeB”:bees.Add(反序列化(块));break;
//…案例
//默认值:。。。
}
}
var复合=新
{
As=ays,
Bs=蜜蜂
};
//这是可以的,但是如果你需要加速,请看
// https://stackoverflow.com/questions/58138793/system-text-json-jsonelement-toobject-workaround
静态T反序列化(JsonElement e)=>JsonSerializer.Deserialize(e.GetRawText(),选项:新的JsonSerializerOptions{PropertyNameCaseSensitive=true});
一种方法是,创建一个自定义反序列化类(检查)编辑->粘贴特殊->粘贴JSON为类这行“descriptiontext”中缺少一个逗号:“这是lost santos的美好一天”
,因为这两个类之间唯一的区别是Title
具有比组件更多的属性,您可以反序列化到列表
。但是,如果需要多态层次结构,则需要编写一个自定义的JsonConverter
。看看,这正是我所希望的。您提到此解决方案“性能不高”,能否为我指出一个方向或给我一个如何使其性能更高的线索?@user2839999很乐意提供帮助!至于性能,我没有很多现成的想法,至少如果它们不涉及手动处理所有字段的话。也许会给你一些想法。另外,请检查此实现的性能是否对您来说是一个值得关注的问题,因为有时“足够好”真的足够好=)
var json = @"[
{
""component"":""components.titletext"",
""id"":1,
""titletext"":""hello""
},
{
""component"":""components.section"",
""id"":2,
""titletext"":""hello"",
""descriptiontext"":""its a beatiful day in lost santos"",
""buttonlink"":""/go""
},
{
""component"":""components.cta"",
""id"":3,
""sectiontitle"":""hello"",
""buttonlink"":""/go"",
""buttontext"":""click me""
}
]";
var deserializeOptions = new JsonSerializerOptions();
deserializeOptions.Converters.Add(new ComponentConverter());
JsonSerializer.Deserialize<List<Component>>(json, deserializeOptions).Dump();
var ays = new List<A>();
var bees = new List<B>();
using var doc = JsonDocument.Parse(json);
foreach (var block in doc.RootElement.EnumerateArray())
{
switch (block.GetProperty("component").GetString())
{
case "typeA": ays.Add(Deserialise<A>(block)); break;
case "typeB": bees.Add(Deserialise<B>(block)); break;
// ... case
//default: ...
}
}
var composite = new
{
As = ays,
Bs = bees
};
// This is OK, but if you need to speed it up, please have a look at
// https://stackoverflow.com/questions/58138793/system-text-json-jsonelement-toobject-workaround
static T Deserialise<T>(JsonElement e) => JsonSerializer.Deserialize<T>(e.GetRawText(), options: new JsonSerializerOptions { PropertyNameCaseInsensitive = true });