我正在尝试使用System.Text.Json.JsonSerializer
来部分地反序列化模型,因此其中一个属性被读取为包含原始JSON的字符串。
public class SomeModel
{
public int Id { get; set; }
public string Name { get; set; }
public string Info { get; set; }
}
示例代码
var json = @"{
""Id"": 1,
""Name"": ""Some Name"",
""Info"": {
""Additional"": ""Fields"",
""Are"": ""Inside""
}
}";
var model = JsonSerializer.Deserialize<SomeModel>(json);
应该生成模型,其中Info
属性将原始JSON中的Info对象作为字符串包含:
{
"Additional": "Fields",
"Are": "Inside"
}
它不能开箱即用并抛出异常:
System.Text.Json.JsonException:---
到目前为止我尝试了什么:
public class InfoToStringConverter : JsonConverter<string>
{
public override string Read(
ref Utf8JsonReader reader, Type type, JsonSerializerOptions options)
{
return reader.GetString();
}
public override void Write(
Utf8JsonWriter writer, string value, JsonSerializerOptions options)
{
throw new NotImplementedException();
}
}
并将其应用于模型中
[JsonConverter(typeof(InfoToStringConverter))]
public string Info { get; set; }
并将选项添加到JsonSerializer
var options = new JsonSerializerOptions();
options.Converters.Add(new InfoToStringConverter());
var model = JsonSerializer.Deserialize<SomeModel>(json, options);
尽管如此,它还是抛出了相同的异常:
System.Text.Json.JsonException:---
烹饪我需要的东西的正确食谱是什么?它使用Newtonsoft.Json
以类似的方式工作。
更新
对我来说,保持嵌套的 JSON 对象尽可能原始是很重要的。因此,我会避免选择反序列化为字典
并序列化回来的选项,因为我害怕引入不需要的更改。
对已接受答案的快速补充:
如果您还需要编写原始JSON值,以下是转换器的Write
方法的实现:
public override void Write(Utf8JsonWriter writer, string value, JsonSerializerOptions options)
{
using (JsonDocument document = JsonDocument.Parse(value))
{
document.RootElement.WriteTo(writer);
}
}
正如github上的dotnet运行时报告所述,这似乎是解决他们决定不实现<code>WriteRawValue
您可以为此使用JsonExtensionData
属性并声明字典
public class SomeModel
{
public int Id { get; set; }
public string Name { get; set; }
[JsonExtensionData]
public Dictionary<string, JsonElement> ExtensionData { get; set; }
[JsonIgnore]
public string Data
{
get
{
return ExtensionData?["Info"].GetRawText();
}
}
}
然后您可以添加一个附加属性以通过
Info
键从此字典中获取字符串。在Data
属性上方的代码中,将包含预期的字符串
{
"Additional": "Fields",
"Are": "Inside"
}
由于某些原因,添加具有相同名称
Info
的属性不起作用,即使使用 JsonIgnore 也是如此
。有关详细信息,请查看处理溢出 JSON。
您还可以将
Info
属性声明为JsonElement
type,并从中获取原始文本
public class SomeModel
{
public int Id { get; set; }
public string Name { get; set; }
public JsonElement Info { get; set; }
}
var model = JsonSerializer.Deserialize<SomeModel>(json);
var rawString = model.Info.GetRawText();
但它会导致模型表示及其序列化的混合。
另一种选择是使用
JsonDocument
解析数据,枚举属性并逐个解析,如下所示
var document = JsonDocument.Parse(json);
foreach (var token in document.RootElement.EnumerateObject())
{
if (token.Value.ValueKind == JsonValueKind.Number)
{
if(token.Value.TryGetInt32(out int number))
{
}
}
if (token.Value.ValueKind == JsonValueKind.String)
{
var stringValue = token.Value.GetString();
}
if (token.Value.ValueKind == JsonValueKind.Object)
{
var rawContent = token.Value.GetRawText();
}
}
找到了正确读取JsonConverter
中嵌套JSON对象的方法。完整的解决方案如下:
public class SomeModel
{
public int Id { get; set; }
public string Name { get; set; }
[JsonConverter(typeof(InfoToStringConverter))]
public string Info { get; set; }
}
public class InfoToStringConverter : JsonConverter<string>
{
public override string Read(
ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
using (var jsonDoc = JsonDocument.ParseValue(ref reader))
{
return jsonDoc.RootElement.GetRawText();
}
}
public override void Write(
Utf8JsonWriter writer, string value, JsonSerializerOptions options)
{
throw new NotImplementedException();
}
}
在代码本身中,甚至不需要创建选项:
var json = @"{
""Id"": 1,
""Name"": ""Some Name"",
""Info"": {
""Additional"": ""Fields"",
""Are"": ""Inside""
}
}";
var model = JsonSerializer.Deserialize<SomeModel>(json);
< code>Info属性中的原始JSON文本甚至包含示例中引入的额外空格,以提高可读性。
并且没有混合模型表示和它的序列化,正如@PavelAnikhomki在他的回答中所说。
问题内容: 我从看起来像这样的API获取JSON: 我尝试了几种方法来在c#对象中表示此JSON(太多内容无法在此处列出)。我已经尝试过使用列表和字典,这是我尝试表示它的最新示例: 这是我用来反序列化JSON的方法: 包含和。并且包含,但是是。因此,除了反序列化之外,什么都没有。 它应该很简单,但是由于某种原因我无法弄清楚正确的对象表示形式 问题答案: 要使用,即: 假设项目名称和随响应而变化,并
问题内容: 如何将上述字符串反序列化为java对象。 我正在使用的类是 问题答案: @基达 我假设您可以控制JSON输入字符串的创建方式。我认为JSON字符串格式不正确,无法对地图类型进行默认的GSON反序列化。 我已经修改了输入字符串供您考虑,这将导致非null的LocalLocationId 如果我对输入字符串的假设不正确,请发表评论。 编辑1:由于无法修改输入,请考虑编写自定义解串器。以下是
问题内容: 我有一些具有各种属性的JSON,其中大多数是简单数据类型。但是,我在JSON中有一个属性,当我将其反序列化为C#类时,我只需要将其反序列化为字符串即可。 JSON示例: 除了将是有效的JSON对象外,“ json”对象没有任何设置结构。 因此,在上面的示例中,“ json”的值是一个JSON对象-但是当它反序列化时,我需要将它作为字符串。 因此,如果我的C#类是: 然后,如果我使用:
我尝试从一个用于存储Spring会话的Redis服务器反序列化String到Java对象,并且我想在Spring框架之外反序列化它。我认为Spring Redis序列化器可能使用默认字符集UTF-8来将Java对象序列化为字符串。 Redis中的字符串: 错误消息: 我知道用UTF-8在Byte[]和String之间的转换很可能是问题所在,但我还是想问一下,是否有人知道如何在不修改序列化部分的情况
问题内容: 我有以下字符串 我想反序列化一个类的对象 我正在使用python 2.6和2.7 问题答案:
问题内容: 我有一个名为的类,该类具有一个作为参数的构造函数: 具有以下属性: 并且是我的应用程序的其他类,并具有以下构造函数: ,并且是的子类。 我想用Gson 反序列化数组,所以我写道: 以定义为: 调试时,实例具有正确的“ MainActivity”作为上下文,而其成员变量的上下文为null。 Gson 使用正确的构造函数创建了对象,但使用默认的无参数构造函数创建了实例。我怎样才能解决这个问