Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/59.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 扩展字典won'的属性;不显示在序列化中_C#_Serialization_Deserialization_.net Core 3.0_System.text.json - Fatal编程技术网

C# 扩展字典won'的属性;不显示在序列化中

C# 扩展字典won'的属性;不显示在序列化中,c#,serialization,deserialization,.net-core-3.0,system.text.json,C#,Serialization,Deserialization,.net Core 3.0,System.text.json,我扩展了一个字典(这是翻译的完美数据结构),并添加了一个标记,告诉您将执行哪种翻译 internal class Translation : Dictionary<string, string> { public string Name { get; set; } } 我怀疑我需要实现一个定制的序列化程序,但对于这个简单的例子来说,这太麻烦了。我的经验告诉我,工具中捆绑了一种整洁、流畅的方法(我根本没有意识到) 怎么做?或者,如果不可能顺利,为什么这是一个复杂的问题(我显然没有

我扩展了一个字典(这是翻译的完美数据结构),并添加了一个标记,告诉您将执行哪种翻译

internal class Translation : Dictionary<string, string>
{
  public string Name { get; set; }
}
我怀疑我需要实现一个定制的序列化程序,但对于这个简单的例子来说,这太麻烦了。我的经验告诉我,工具中捆绑了一种整洁、流畅的方法(我根本没有意识到)

怎么做?或者,如果不可能顺利,为什么这是一个复杂的问题(我显然没有意识到)

我希望下面的表单上有JSON

{
  "name": "donkey",
  "key1": "value1",
  "key2": "value2",
  "key3": "value3",
}

当然,我可以通过在字典中添加一个项来解决这个问题,其中键是name,值是duck。但这是一个务实的解决方案,我更愿意把它作为我的退路。目前,我有一些额外的时间,想玩的结构。此外,我可以想象名称可能会变成一个int而不是字符串,或者甚至可能是一个更复杂的结构来描述,例如时间戳或其他东西。这将完全打破字典的约定(即字符串到字符串的映射)。

这似乎是设计意图——与Newtonsoft、
JavaScriptSerializer
DataContractJsonSerializer
一样,字典键和值是序列化的,而不是常规属性

作为扩展
字典
的替代方法,您可以通过将字典封装在容器类中并用以下标记字典来获得所需的JSON:

请注意此限制

字典的TKey值必须为,TValue必须为或

(顺便说一句,类似的方法也适用于拥有自己库的Newtonsoft。如果您同时使用这两个库,请确保不要混淆属性。)

演示小提琴#1

如果对数据模型的这种修改不方便,可以引入一个自定义的DTO(反)序列化,如上面的模型,然后将DTO从最终模型映射到最终模型:

internal class Translation : Dictionary<string, string>
{
    public string Name { get; set; }
}

internal class TranslationConverter : JsonConverter<Translation>
{
    internal class TranslationDTO
    {
        public string Name { get; set; }

        [JsonExtensionData]
        public Dictionary<string, object> Data { get; set; }
    }

    public override Translation Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
    {
        var dto = JsonSerializer.Deserialize<TranslationDTO>(ref reader, options);
        if (dto == null)
            return null;
        var translation = new Translation { Name = dto.Name };
        foreach (var p in dto.Data)
            translation.Add(p.Key, p.Value?.ToString());
        return translation;
    }

    public override void Write(Utf8JsonWriter writer, Translation value, JsonSerializerOptions options)
    {
        var dto = new TranslationDTO { Name = value.Name, Data = value.ToDictionary(p => p.Key, p => (object)p.Value) };
        JsonSerializer.Serialize(writer, dto, options);
    }
}
我发现(反)序列化到DTO比直接使用
Utf8JsonReader
Utf8JsonWriter
更简单,因为边缘案例和命名策略会自动处理。只有在表现至关重要的情况下,我才能直接与读者和作者合作

无论使用哪种方法,都需要将JSON中的
“name”
绑定到模型中的
name


Demo fiddle#2.

您想继续使用本机的
System.Text.Json
还是想使用Json.net?@Cid在这种情况下,我想尝试一下新产品,转换没有更大的风险,它提供了一个扩大能力的机会。因为时间不太重要(圣诞假期之类的),我可以在老板不在我身后的情况下浪费一些精力,呵呵。否则,我会选择牛顿,因为它周围有大量的博客这与newtonsoft.json解释的问题相同。您可能必须使用自定义转换器hower,一个懒惰的解决方法可能是更改类的结构,而不是扩展
字典
,将其用作类属性
internal class Translation
{
    public string Name { get; set; }

    [JsonExtensionData]
    public Dictionary<string, object> Data { get; set; } = new Dictionary<string, object>();
}
var translation = new Translation
{
    Name = "donkey",
    Data = 
    {
        {"key1", "value1"},
        {"key2", "value2"},
        {"key3", "value3"},
    },
};

var options = new JsonSerializerOptions
{
    PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
    // Other options as required
    WriteIndented = true,
};

var json = JsonSerializer.Serialize(translation, options);
internal class Translation : Dictionary<string, string>
{
    public string Name { get; set; }
}

internal class TranslationConverter : JsonConverter<Translation>
{
    internal class TranslationDTO
    {
        public string Name { get; set; }

        [JsonExtensionData]
        public Dictionary<string, object> Data { get; set; }
    }

    public override Translation Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
    {
        var dto = JsonSerializer.Deserialize<TranslationDTO>(ref reader, options);
        if (dto == null)
            return null;
        var translation = new Translation { Name = dto.Name };
        foreach (var p in dto.Data)
            translation.Add(p.Key, p.Value?.ToString());
        return translation;
    }

    public override void Write(Utf8JsonWriter writer, Translation value, JsonSerializerOptions options)
    {
        var dto = new TranslationDTO { Name = value.Name, Data = value.ToDictionary(p => p.Key, p => (object)p.Value) };
        JsonSerializer.Serialize(writer, dto, options);
    }
}
var translation = new Translation
{
    Name = "donkey",
    ["key1"] = "value2",
    ["key2"] = "value2",
    ["key3"] = "value3",
};

var options = new JsonSerializerOptions
{
    Converters = { new TranslationConverter() },
    PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
    // Other options as required
    WriteIndented = true,
};

var json = JsonSerializer.Serialize(translation, options);