我想格式化 c# 字典的元素

i want to format the element of a c# dictionary

我的数据库中有一个 table 用于存储翻译

ResourseKey ResourseText LanguageId
Home Home 1
Home Hem 2
Search Search 1
Search Sök 2

和语言 table

Id Language
1 English
2 Swedish

我正在尝试 return 一个看起来像这样的对象

{
   "Home":{
      "Swedish":"Hem",
      "English":"Home"
   },
   "Search":{
      "Swedish":"Sök",
      "English":"Search"
   }
}

我开始做

var data = await _context.Translations
             .Include(x => x.Language)
             .ToListAsync();
return data.ToLookup(p => p.ResourseKey , p => p).ToDictionary(x => x.Key, x => x.ToArray());

但我不能再继续了

我想将查找短语格式化为 return 所需的结构,而不是 return 只 p

我当然可以在客户端通过 js 修复它,但我想在服务器端完成所有繁重的工作

如果我的问题是非结构化的,我真的很抱歉这是第一次 post 关于 SOF

的问题

我认为 Inner Join 可以在这种情况下为您提供帮助。

考虑如下两个实体:

public class Word
{
    public int Id { get; set; }
    public string ResourseKey { get; set; }
    public string ResourseText { get; set; }
    public string Language { get; set; }
}

另一个:

public class Language
{
    public int Id { get; set; }
    public string Lang { get; set; }
}

现在我们为内部联接初始化一些数据和select我们需要的数据:

    internal class Program
{
    static void Main(string[] args)
    {
        List<Language> languages = new List<Language>()
        {
            new Language{Id = 1, Lang="English"},
            new Language{Id = 2, Lang="Swedish"}
        };

        List<Word> words = new List<Word>()
        {
            new Word{Id = 1, ResourseKey = "Home", ResourseText = "Home", Language = "English"},
            new Word{Id = 1, ResourseKey = "Home", ResourseText = "Hem", Language = "Swedish"},
            new Word{Id = 1, ResourseKey = "Search", ResourseText = "Search", Language = "English"},
            new Word{Id = 1, ResourseKey = "Search", ResourseText = "Sök", Language = "Swedish"},
        };

        var innerGroupJoinQuery =
                from lang in languages
                join word in words on lang.Lang equals word.Language into prodGroup
                select new { LangName = lang.Lang, Words = prodGroup };

        foreach (var item in innerGroupJoinQuery)
        {
            Console.WriteLine($"Name: {item.LangName}");
            foreach (var w in item.Words)
            {
                Console.WriteLine($"---Word: {w.ResourseText}");
            }
        }

    }
}

要格式化 json 您可以使用 JsonConverter class,write 方法是生成输出的方法。参数编写器有很多方法可以帮助你生成你想要的输出。

public class ResourceByLanguage
{
    public string Language { get; set; }
    public string Value { get; set; }

    public ResourceByLanguage(Resource resource)
    {
        Language = resource.Language.Title;
        Value = resource.Text;
    }
}

和:

public class ResourceByLanguageConverter : JsonConverter<ResourceByLanguage[]>
{
    public override ResourceByLanguage[]? Read(ref Utf8JsonReader reader, Type typeToConvert,
        JsonSerializerOptions options)
    {
        throw new NotImplementedException();
    }

    public override void Write(Utf8JsonWriter writer, ResourceByLanguage[] values, JsonSerializerOptions options)
    {
        writer.WriteStartObject();
        foreach (var value in values)
        {
            writer.WritePropertyName(value.Language);
            writer.WriteStringValue(value.Value);
        }

        writer.WriteEndObject();
    }
}

和(在控制台应用程序上):

var result = resources
    .GroupBy(p => p.ResourceKey)
    .ToDictionary(p => p.Key,
        p => p.Select(resource => new ResourceByLanguage(resource)).ToArray());

var jsonConverter = new JsonSerializerOptions()
{
    Converters = {new ResourceByLanguageConverter()}
};
var json = JsonSerializer.Serialize(result, jsonConverter);
Console.WriteLine(json);

将生成此输出:

{"home":{"English":"Home","Swedish":"Hem"},"search":{"English":"Search"}}

如果您使用的是 aspnet,则通过在 services.AddController 行(可以在 Program.cs 或 Startup.cs 上)添加此代码来注册转换器:

services.AddControllers().AddJsonOptions(j => 
        {
            j.JsonSerializerOptions.Converters.Add(new ResourceByLanguageConverter());
        });

然后使用:

return resources
     // here you have to add the include that you used on question
    .GroupBy(p => p.ResourceKey)
    .ToDictionary(p => p.Key,
        p => p.Select(resource => new ResourceByLanguage(resource)).ToArray());

和 aspnet 你做的工作。