如何在c#中找到json记录的所有不同键?

如何在c#中找到json记录的所有不同键?,c#,json,C#,Json,为什么这个问题不重复?(在看到评论后添加) 它与实体框架无关 它必须解析巨大的json文件并找到不同的键,但不能找到记录 我有200多个文件,每个都是2+GB,这意味着总大小是400+GB。这些文件中的每一行都是一个json字符串。我事先没有记录的json模式。我的工作是找到那些文件中的所有密钥 我编写了以下代码以从所有这些json记录中获取所有不同的键。我从main使用多线程for循环调用以下方法 private void GetTokensFromJson(string filePath

为什么这个问题不重复?(在看到评论后添加)

  • 它与实体框架无关
  • 它必须解析巨大的json文件并找到不同的键,但不能找到记录
我有200多个文件,每个都是2+GB,这意味着总大小是400+GB。这些文件中的每一行都是一个json字符串。我事先没有记录的
json模式
。我的工作是找到那些文件中的所有密钥

我编写了以下代码以从所有这些json记录中获取所有不同的键。我从
main
使用多线程
for循环
调用以下方法

private void GetTokensFromJson(string filePath)
        {
            IEnumerable<string> txts = File.ReadLines(filePath, Encoding.UTF8);

            Console.WriteLine(txts.Count());

            List<string> distinctKeys = new List<string>();

            foreach (var text in txts)
            {

                    string pattern = "{\"";

                    foreach (Match m in Regex.Matches(text, pattern))
                    {
                        //string matchValue = m.Value;
                        int matchIndex = m.Index;
                        string subStr=text.Substring(matchIndex+2, text.Length - matchIndex - 3);
                        int quoteIndex=subStr.IndexOf('\"');
                        string jsonKey = subStr.Substring(0, quoteIndex);
                        if (!distinctKeys.Contains(jsonKey) && !jsonKey.Contains("\\"))
                        {
                            Console.WriteLine(jsonKey);
                            distinctKeys.Add(jsonKey);
                        }
                    }

                string secondPattern="\":";
                foreach (Match m in Regex.Matches(text, secondPattern))
                {
                    int matchIndex = m.Index;
                    string revJsonKKey = "";
                    while(matchIndex>0)
                    {
                        matchIndex--;
                        if (text[matchIndex] != '\"')
                            revJsonKKey += text[matchIndex];
                        else
                            break;
                    }

                    IEnumerable<char> jsonKeyCharArray = revJsonKKey.Reverse();
                    string jsonKey="";
                    foreach(char c in jsonKeyCharArray)
                    {
                        jsonKey += c;
                    }

                    if (!distinctKeys.Contains(jsonKey) && !jsonKey.Contains("\\"))
                    {
                        Console.WriteLine(jsonKey);
                        distinctKeys.Add(jsonKey);
                    }

                }

            }
预期的输出是
id、名称、部门、部门->名称、部门->部门tid
。输出的格式并不重要。请注意,并非所有json记录都具有所有键,并且json记录可以包含嵌套的json记录

我有两个问题

  • 我在代码中做错了什么
  • 当我将输入作为复杂的json记录时,是否有内置或第三方dll将输出作为json键

  • 将字符串读入JSON.NET并将它们转换为Jobjects

    然后遍历作业对象

     foreach ( jobject in jobjects )   
    {
     IList<string> keys = jobject .Properties().Select(p => p.Name).ToList();
    }
    
    就像

     private void GetTokensFromJson(string filePath)
                {
                    IEnumerable<string> txts = File.ReadLines(filePath, Encoding.UTF8);
        List<JObject> jObjects = new List<JObject>() {};
        IList<string> keyslist;
    
                    Console.WriteLine(txts.Count());
    
                    List<string> distinctKeys = new List<string>();
    
                    foreach (var text in txts)
                    {
    
                          var obj = JObject.Parse(text); 
                          jObjects.add(obj);  
    
    
                    }
        for each ( jobject in jobjects )   
        {
         IList<string> keys = jobject .Properties().Select(p => p.Name).ToList();
        keyslist.add(keys);
        }
        keyslist.distinct();
    
             }
    
    private void GetTokensFromJson(字符串文件路径)
    {
    IEnumerable txts=File.ReadLines(filePath,Encoding.UTF8);
    List jObjects=new List(){};
    IList密钥列表;
    Console.WriteLine(txts.Count());
    List distinctKeys=新列表();
    foreach(txts中的var文本)
    {
    var obj=JObject.Parse(文本);
    jObjects.add(obj);
    }
    对于每个(作业项目中的作业项目)
    {
    IList keys=jobject.Properties().Select(p=>p.Name.ToList();
    keyslist.add(键);
    }
    keyslist.distinct();
    }
    
    将字符串读入JSON.NET并将其转换为作业对象

    然后遍历作业对象

     foreach ( jobject in jobjects )   
    {
     IList<string> keys = jobject .Properties().Select(p => p.Name).ToList();
    }
    
    就像

     private void GetTokensFromJson(string filePath)
                {
                    IEnumerable<string> txts = File.ReadLines(filePath, Encoding.UTF8);
        List<JObject> jObjects = new List<JObject>() {};
        IList<string> keyslist;
    
                    Console.WriteLine(txts.Count());
    
                    List<string> distinctKeys = new List<string>();
    
                    foreach (var text in txts)
                    {
    
                          var obj = JObject.Parse(text); 
                          jObjects.add(obj);  
    
    
                    }
        for each ( jobject in jobjects )   
        {
         IList<string> keys = jobject .Properties().Select(p => p.Name).ToList();
        keyslist.add(keys);
        }
        keyslist.distinct();
    
             }
    
    private void GetTokensFromJson(字符串文件路径)
    {
    IEnumerable txts=File.ReadLines(filePath,Encoding.UTF8);
    List jObjects=new List(){};
    IList密钥列表;
    Console.WriteLine(txts.Count());
    List distinctKeys=新列表();
    foreach(txts中的var文本)
    {
    var obj=JObject.Parse(文本);
    jObjects.add(obj);
    }
    对于每个(作业项目中的作业项目)
    {
    IList keys=jobject.Properties().Select(p=>p.Name.ToList();
    keyslist.add(键);
    }
    keyslist.distinct();
    }
    
    用Json.net试试,该Path属性包含该对象的完整路径

     private static void GetKeys(JObject obj, List<string> keys)
        {
            var result = obj.Descendants()
                .Where(f => f is JProperty) //.Where(f => f is JProperty) 
                .Select(f => f as JProperty)// and .Select(f => f as JProperty) can be replaced with .OfType<JProperty>()
                .Select(f=>f.Path)
                .Where(f=> !keys.Contains(f));
            keys.AddRange(result);
        }
    
        static void Main(string[] args)
        {         
            IEnumerable<string> txts = @"{'id':'123', 'name':'hello, world',     'department':[{'name':'dept1', 'deptID':'123'}]}
    {'id':'456324', 'department':[{'name':'dept2', 'deptID':'456'}]}".Split("\r\n".ToArray(),StringSplitOptions.RemoveEmptyEntries);
            List<string> keys = new List<string>();
            foreach (var item in txts)
            {
                var obj = JObject.Parse(item);
                GetKeys(obj, keys);
            }
    
    private static void GetKeys(JObject对象,列表键)
    {
    var result=obj.subjects()
    。其中(f=>f是JProperty)/。其中(f=>f是JProperty)
    .Select(f=>f作为JProperty)//和.Select(f=>f作为JProperty)可以替换为.OfType()
    .选择(f=>f.Path)
    其中(f=>!keys.Contains(f));
    添加范围(结果);
    }
    静态void Main(字符串[]参数)
    {         
    IEnumerable txts=@“{'id':'123','name':'hello,world','department':[{'name':'dept1','deptID':'123'}]}
    {'id':'456324','department':[{'name':'dept2','deptID':'456'}]}.Split(“\r\n.ToArray(),StringSplitOptions.RemoveEmptyEntries”);
    列表键=新列表();
    foreach(txts中的var项目)
    {
    var obj=JObject.Parse(项目);
    获取密钥(obj,密钥);
    }
    

    }

    尝试使用Json.net,该路径属性包含该对象的完整路径

     private static void GetKeys(JObject obj, List<string> keys)
        {
            var result = obj.Descendants()
                .Where(f => f is JProperty) //.Where(f => f is JProperty) 
                .Select(f => f as JProperty)// and .Select(f => f as JProperty) can be replaced with .OfType<JProperty>()
                .Select(f=>f.Path)
                .Where(f=> !keys.Contains(f));
            keys.AddRange(result);
        }
    
        static void Main(string[] args)
        {         
            IEnumerable<string> txts = @"{'id':'123', 'name':'hello, world',     'department':[{'name':'dept1', 'deptID':'123'}]}
    {'id':'456324', 'department':[{'name':'dept2', 'deptID':'456'}]}".Split("\r\n".ToArray(),StringSplitOptions.RemoveEmptyEntries);
            List<string> keys = new List<string>();
            foreach (var item in txts)
            {
                var obj = JObject.Parse(item);
                GetKeys(obj, keys);
            }
    
    private static void GetKeys(JObject对象,列表键)
    {
    var result=obj.subjects()
    。其中(f=>f是JProperty)/。其中(f=>f是JProperty)
    .Select(f=>f作为JProperty)//和.Select(f=>f作为JProperty)可以替换为.OfType()
    .选择(f=>f.Path)
    其中(f=>!keys.Contains(f));
    添加范围(结果);
    }
    静态void Main(字符串[]参数)
    {         
    IEnumerable txts=@“{'id':'123','name':'hello,world','department':[{'name':'dept1','deptID':'123'}]}
    {'id':'456324','department':[{'name':'dept2','deptID':'456'}]}.Split(“\r\n.ToArray(),StringSplitOptions.RemoveEmptyEntries”);
    列表键=新列表();
    foreach(txts中的var项目)
    {
    var obj=JObject.Parse(项目);
    获取密钥(obj,密钥);
    }
    

    }让我们来算一下,好吗。你有:

    • 200个文件
    • 至少为2 GB
    • 如果是一行,平均120个字符(240字节)
    这使得400 GB的内部内存仅用于保存所有内容和 1789569707,即近20亿行

    显然,您这里的问题不是与解析相关的问题,而是以增量方式管理内存和索引键,使用并非全部驻留在内存中的中间结果

    使用您现在拥有的简单列表跟踪您的关键点,并假设您的关键点的1/20是唯一的:

    • 您现在必须在索引列表中维护1.25亿个关键条目
    • 如果单个键索引项所需的存储空间为80字节,那么这将添加到占用9 GB内存的列表中
    在列表(1.25亿项)中搜索新行的重复项将非常缓慢


    您可能需要研究map/reduce样式的算法,以了解如何实现类似的功能。

    让我们来计算一下,好吗。你有:

    • 200个文件
    • 至少为2 GB
    • 如果是一行,平均120个字符(240字节)
    那是4英镑