解决 How to get 价值观 from elements in JSON without indexing?

WeyardWiz

会员
已加入
2020年10月23日
留言内容
23
编程经验
3-5
I have the following code that extracts json elements 价值观 和 outputs to csv:

C#:
public static void Json_to_Csv(string jsonInputFile, string csvFile)
{
    using (var p = new ChoJSONReader(jsonInputFile).WithJSONPath("$..readResults")) // "readResults": [
    {
        using (var w = new ChoCSVWriter(csvFile).WithFirstLineHeader())
        {
            w.Write(p
                .Select(r1 =>
                {
                    var lines = (dynamic[])r1.lines;
                    return new
                    {
                        FileName = jsonInputFile,
                        Page = r1.page,
                        PracticeName = lines[2].text,
                        OwnerFullName = lines[4].text,
                        OwnerEmail = lines[6].text,
                    };
                }
        }
    }
}

csv输出:

File 名称,Page,Practice 名称,Owner Full 名称,Owner 电子邮件
file1.json,1,Some Practice 名称,Bob Lee,鲍勃@ someemail.com

当前在每个项目上没有其他上下文信息可以引用它们,因此唯一的方法是通过索引,例如线[2]

This works for now but I may have other JSON files that have an extra field, therefore the 价值观 pulled will be wrong.

为了解决这种情况, how can i pull the 价值观 contextually instead of indexing the lines?

我试过了
C#:
PracticeName = lines["Practice 名称"].text

但我明白了 无法将类型字符串隐式转换为int 错误


file1.json示例:

JSON:
{
  "status": "succeeded",
  "createdDateTime": "2020-10-22T19:35:35Z",
  "lastUpdatedDateTime": "2020-10-22T19:35:36Z",
  "analyzeResult": {
    "version": "3.0.0",
    "readResults": [
      {
        "page": 1,
        "angle": 0,
        "width": 8.5,
        "height": 11,
        "unit": "inch",
        "lines": [        
          {
            "boundingBox": [
              0.5016,
              1.9141,
              2.5726,
              1.9141,
              2.5726,
              2.0741,
              0.5016,
              2.0741
            ],          
           "text": "Account Information",
            "words": [
              {
                "boundingBox": [
                  0.5016,
                  1.9345,
                  1.3399,
                  1.9345,
                  1.3399,
                  2.0741,
                  0.5016,
                  2.0741
                ],
                "text": "Account",
                "confidence": 1
              },
              {
                "boundingBox": [
                  1.3974,
                  1.9141,
                  2.5726,
                  1.9141,
                  2.5726,
                  2.0741,
                  1.3974,
                  2.0741
                ],
                "text": "Information",
                "confidence": 1
              }
            ]
          },
          {
            "boundingBox": [
              1.7716,
              2.4855,
              2.8793,
              2.4855,
              2.8793,
              2.6051,
              1.7716,
              2.6051
            ],
            "text": "Practice 名称",
            "words": [
              {
                "boundingBox": [
                  1.7716,
                  2.4855,
                  2.3803,
                  2.4855,
                  2.3803,
                  2.6051,
                  1.7716,
                  2.6051
                ],
                "text": "Practice",
                "confidence": 1
              },
              {
                "boundingBox": [
                  2.4362,
                  2.4948,
                  2.8793,
                  2.4948,
                  2.8793,
                  2.6051,
                  2.4362,
                  2.6051
                ],
                "text": "Name",
                "confidence": 1
              }
            ]
          },
          {
            "boundingBox": [
              2.9993,
              2.5257,
              4.7148,
              2.5257,
              4.7148,
              2.714,
              2.9993,
              2.714
            ],
            "text": "Some Practice 名称",
            "words": [
              {
                "boundingBox": [
                  3.0072,
                  2.5385,
                  3.6546,
                  2.5284,
                  3.6516,
                  2.7131,
                  3.0105,
                  2.712
                ],
                "text": "Some",
                "confidence": 0.984
              },
              {
                "boundingBox": [
                  3.6887,
                  2.5281,
                  4.2112,
                  2.5262,
                  4.2028,
                  2.7159,
                  3.6854,
                  2.7132
                ],
                "text": "Parctice",
                "confidence": 0.986
              },
              {
                "boundingBox": [
                  4.2453,
                  2.5263,
                  4.7223,
                  2.5297,
                  4.7091,
                  2.72,
                  4.2366,
                  2.7161
                ],
                "text": "Name",
                "confidence": 0.986
              }
            ]
          },
          {
            "boundingBox": [
              1.6116,
              2.9999,
              2.8816,
              2.9999,
              2.8816,
              3.1158,
              1.6116,
              3.1158
            ],
            "text": "Owner Full 名称",
            "words": [
              {
                "boundingBox": [
                  1.6116,
                  3.0039,
                  2.1026,
                  3.0039,
                  2.1026,
                  3.1157,
                  1.6116,
                  3.1157
                ],
                "text": "Owner",
                "confidence": 1
              },
              {
                "boundingBox": [
                  2.1541,
                  2.9999,
                  2.3784,
                  2.9999,
                  2.3784,
                  3.1158,
                  2.1541,
                  3.1158
                ],
                "text": "Full",
                "confidence": 1
              },
              {
                "boundingBox": [
                  2.4384,
                  3.0052,
                  2.8816,
                  3.0052,
                  2.8816,
                  3.1155,
                  2.4384,
                  3.1155
                ],
                "text": "Name",
                "confidence": 1
              }
            ]
          },
          {
            "boundingBox": [
              2.9993,
              3.0242,
              3.6966,
              3.0242,
              3.6966,
              3.2125,
              2.9993,
              3.2014
            ],
            "text": "Bob Lee",
            "words": [
              {
                "boundingBox": [
                  3.0063,
                  3.0303,
                  3.3439,
                  3.0349,
                  3.3461,
                  3.2125,
                  3.007,
                  3.2081
                ],
                "text": "Bob",
                "confidence": 0.987
              },
              {
                "boundingBox": [
                  3.3788,
                  3.0349,
                  3.6931,
                  3.0326,
                  3.697,
                  3.2121,
                  3.3813,
                  3.2125
                ],
                "text": "Lee",
                "confidence": 0.983
              }
            ]
          },
          {
            "boundingBox": [
              1.945,
              3.5063,
              2.8748,
              3.5063,
              2.8748,
              3.6261,
              1.945,
              3.6261
            ],
            "text": "Owner 电子邮件",
            "words": [
              {
                "boundingBox": [
                  1.945,
                  3.5143,
                  2.4359,
                  3.5143,
                  2.4359,
                  3.6261,
                  1.945,
                  3.6261
                ],
                "text": "Owner",
                "confidence": 1
              },
              {
                "boundingBox": [
                  2.4874,
                  3.5063,
                  2.8748,
                  3.5063,
                  2.8748,
                  3.6259,
                  2.4874,
                  3.6259
                ],
                "text": "Email",
                "confidence": 1
              }
            ]
          },
          {
            "boundingBox": [
              3.0104,
              3.5005,
              4.6042,
              3.5005,
              4.6042,
              3.6888,
              3.0104,
              3.6777
            ],
            "text": "[email protected]",
            "words": [
              {
                "boundingBox": [
                  3.0212,
                  3.5047,
                  4.5837,
                  3.5039,
                  4.5769,
                  3.6886,
                  3.0129,
                  3.6787
                ],
                "text": "[email protected]",
                "confidence": 0.951
              }
            ]
          }
        ]
      }
    ]
  }
}
 
由主持人最后编辑:
Solution
以下将对输出到控制台:
C#:
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using Newtonsoft.Json;

class RootObject
{
    [JsonProperty("analyzeResult")]
    public AnalyzeResult AnalyzeResult { get; set; }
}

class AnalyzeResult
{
    [JsonProperty("readResults")]
    public ReadResults[] ReadResults { get; set; }
}

class ReadResults
{
    [JsonProperty("lines")]
    public Line[] Lines { get; set; }
}

class Line
{
    [JsonProperty("text")]
    public string Text { get; set; }

    public override string ToString() => Text;
}

public static class IEnumerableExtensions
{
    public static IEnumerable<KeyValuePair<T, T>> Pairs<T>(this IEnumerable<T> items)
    {...

跳伞

工作人员
已加入
2019年4月6日
留言内容
2,497
地点
弗吉尼亚州切萨皮克
编程经验
10+
您将使用LINQ to Objects过滤到所需的对象实例。这很重要,您需要将JSON反序列化为对象。我不熟悉ChoJSONReader,但我知道我已经不喜欢它,因为它不遵循.NET Framework的命名约定。
 

WeyardWiz

会员
已加入
2020年10月23日
留言内容
23
编程经验
3-5
您将使用LINQ to Objects过滤到所需的对象实例。这很重要,您需要将JSON反序列化为对象。我不熟悉ChoJSONReader,但我知道我已经不喜欢它,因为它不遵循.NET Framework的命名约定。
我尝试遵循反序列化方法,但是对于我想做的事情,实现起来似乎太复杂了。我发现ChoJSONReader可作为替代方案,因为到目前为止,它是实现我想要的目标的唯一方法。
如果您能给我看一个上面提到的例子,我将不胜感激,因为这可能有助于改善我目前的设计,并使事情变得更加灵活。
 

羊皮

退休程序员
工作人员
已加入
2018年9月5日
留言内容
1,921
地点
英国
编程经验
10+
如果您知道文件的内容,则可以将数据填充到一个类中。从该类中,您可以轻松地将其序列化为csv文件。我向跳伞运动员展示另一个主题的一种方法是填充方法: 填充对象 他承认这很有用。 序列化反序列化 可以在这些页面上找到其他有用的示例。
 

WeyardWiz

会员
已加入
2020年10月23日
留言内容
23
编程经验
3-5
如果您知道文件的内容,则可以将数据填充到一个类中。从该类中,您可以轻松地将其序列化为csv文件。我向跳伞运动员展示另一个主题的一种方法是填充方法: 填充对象 他承认这很有用。 序列化反序列化 可以在这些页面上找到其他有用的示例。
通常情况下,我们将拥有一个属性,然后为其赋予一个值,如下所示:

C#:
public string Test { get; set; }

        public Program()

        {

            Test = "Test";

        }

然后,我们可以在其他位置基于属性名称获取值。

但是在这个json中,"Owner Full 名称" 和 "Bob Lee"不是属性和值之间的关系,而是两个不相关对象中Text属性的值,如下所示:

C#:
public class Line

    {

        public float[] BoundingBox { get; set; }

        public string Text { get; set; }

        public Word[] Words { get; set; }

    }

 

    ***********************



    new Line() { Text = "Owner Full 名称" };

    new Line() { Text = "Bob Lee" };

除了在我的原始代码中手动指定外,我们无法在它们之间建立连接。

因此,在尝试将id导入到csv文件之前,id必须重建一个合格的JSON,但是问题在于此json是来自Azure计算机视觉读取API响应的结果。

我猜我当前使用choJSON的代码是完成此操作的唯一方法。
 

羊皮

退休程序员
工作人员
已加入
2018年9月5日
留言内容
1,921
地点
英国
编程经验
10+
如果您不愿意阅读我给您提供的链接上的文档,您将发现它是不可能的,而且非常简单。
 

WeyardWiz

会员
已加入
2020年10月23日
留言内容
23
编程经验
3-5
如果您不愿意阅读我给您提供的链接上的文档,您将发现它是不可能的,而且非常简单。
我看过了
Populating the object works in the Account class example they show because it's a property/attribute to value relationship. Therefore, deserializing it dynamically is very easily done. However, in the json I've given in my post, this method does not work because the attributes 和 supposed ”values” have no connection. As a human, I can tell for example that ”Bob Lee” is the value of ”Owner Full 名称 ” property but the program cannot distinguish that like I can. Because there is no connection between them.

唯一的方法是手动为每个文件填充一个类,这违背了使用程序执行此操作的目的,因为我可以通过读取原始pdf文件直接在csv中手动填充数据。
 

跳伞

工作人员
已加入
2019年4月6日
留言内容
2,497
地点
弗吉尼亚州切萨皮克
编程经验
10+
查看那里的JSON,看起来它大致映射到以下类结构:
C#:
class RootObject
{
    AnalyzeResult AnalyzeResult { get; set; }
}

class AnalyzeResult
{
    ReadResults ReadResults { get; set; }
}

class ReadResults
{
    Line [] Lines { get; set; }
}

class Line
{
    string Text { get; set; }
    Word [] Words { get; set; }
}

class Word
{
    string Text { get; set; }
}

If you know that each pair of lines is always a name-value pair, then you can just ingest the lines in pairs 和 setup the 价值观 to go out into the CSV.

顺便说一句,我浏览了GitHub中的ChoJSONReader的源代码。它只是NewtonSoft JSON.NET库的包装。
 

WeyardWiz

会员
已加入
2020年10月23日
留言内容
23
编程经验
3-5
有趣的...您可以演示“将线成对地浸入并设置要放入CSV的值”吗?我认为迫使我使用choJSONReader的原因是choCSVWriter,因为最终这就是我想要的,将属性/值写入csv。
如果这只是JSON.NET库的包装,是否意味着有可能 pull the 价值观 contextually instead of indexing the lines? And if so, how?

Mod编辑:无需整体引用或直接引用您上方的人。
 
由主持人最后编辑:

跳伞

工作人员
已加入
2019年4月6日
留言内容
2,497
地点
弗吉尼亚州切萨皮克
编程经验
10+
以下将对输出到控制台:
C#:
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using Newtonsoft.Json;

class RootObject
{
    [JsonProperty("analyzeResult")]
    public AnalyzeResult AnalyzeResult { get; set; }
}

class AnalyzeResult
{
    [JsonProperty("readResults")]
    public ReadResults[] ReadResults { get; set; }
}

class ReadResults
{
    [JsonProperty("lines")]
    public Line[] Lines { get; set; }
}

class Line
{
    [JsonProperty("text")]
    public string Text { get; set; }

    public override string ToString() => Text;
}

public static class IEnumerableExtensions
{
    public static IEnumerable<KeyValuePair<T, T>> Pairs<T>(this IEnumerable<T> items)
    {
        var enumerator = items.GetEnumerator();

        while (enumerator.MoveNext())
        {
            var name = enumerator.Current;
            if (enumerator.MoveNext())
                yield return new KeyValuePair<T, T>(name, enumerator.Current);
            else
                throw new InvalidDataException("Odd number of items found in IEnumerable<T>");
        }
    }
}

class Program
{
    static IEnumerable<Line> GetLines(string jsonText)
    {
        var root = JsonConvert.DeserializeObject<RootObject>(jsonText);
        return root.AnalyzeResult
                   .ReadResults
                   .SelectMany(r => r.Lines);
    }

    static void Main(string[] args)
    {
        var lines = GetLines(File.ReadAllText("response.json"));

        // Skip(1) to skip over the "Account Information" Line.
        var pairs = lines.Skip(1).Pairs();

        foreach(var pair in pairs)
            Console.WriteLine($"{pair.Key}: {pair.Value}");
    }
}

产生以下输出:
Code:
Practice 名称: Some Practice 名称
Owner Full 名称: 鲍勃·李
Owner 电子邮件: [email protected]
 
Last edited:

WeyardWiz

会员
已加入
2020年10月23日
留言内容
23
编程经验
3-5
以下将对输出到控制台:
C#:
    static void Main(string[] args)
    {
        // Skip(1) to skip over the "Account Information" Line.
        var pairs = lines.Skip(1).Pairs();
    }
太棒了,谢谢跳伞运动员。虽然,我不必显式跳过某条线的事实,即"Account Information", mean that Im still technically confined to the JSON structure? In other words, doesnt this mean that if i had another JSON file structure with more fields preceding even 帐户信息, that I would have to adjust the skip once again in order to make sure the first field it reads is Practice 名称?
Is there a way then to make it even more dynamic so that it directly goes to Practice 名称 instead of just having to skip() over a certain number of Lines?
就像是:
C#:
var pairs = lines.SkipAllUntil("Practice 名称").Pairs();
 

跳伞

工作人员
已加入
2019年4月6日
留言内容
2,497
地点
弗吉尼亚州切萨皮克
编程经验
10+
I only put in the skip there as hard coded because I was trying to highlight the pulling of JSON elements in pairs since that is what you asked about. With software anything is possible. It just depends how much time, energy, 和 money you want to invest. To answer your new question, you can operate on any IEnumerable using LINQ's SkipWhile().
 

WeyardWiz

会员
已加入
2020年10月23日
留言内容
23
编程经验
3-5
I only put in the skip there as hard coded because I was trying to highlight the pulling of JSON elements in pairs since that is what you asked about. With software anything is possible. It just depends how much time, energy, 和 money you want to invest. To answer your new question, you can operate on any IEnumerable using LINQ's SkipWhile().
我懂了。因此,香港专业教育学院尝试以下方法:
C#:
var pairs = lines.SkipWhile(r => r == "Practice 名称").Pairs();
但是我越来越 "运算符'=='不能应用于'Line'和'String'类型的操作数"

我想我理解此错误的含义,因为Line不是String类型,无法进行这样的直接比较。

香港专业教育学院想好了,很容易,我只是要将行转换为字符串类型:
C#:
var pairs = lines.SkipWhile(r => r.ToString() == "Practice 名称").Pairs();

但是,这不仅打印出来"Account Information",但配对在控制台输出上变得混乱,然后出现异常
"无法访问的代码,“在IEnumerable中发现奇数个项目<T>'"

但是无论如何,这是否意味着必须总是使用==行才能使用while练习名称?这意味着只有部分JSON被执行?

请原谅我提出了很多问题,我用C#编程的最后一次是6年前,而香港专业教育学院最近不得不再次使用它。不过,到现在为止,真的很感谢您的指导!
 

跳伞

工作人员
已加入
2019年4月6日
留言内容
2,497
地点
弗吉尼亚州切萨皮克
编程经验
10+
翻转逻辑。
C#:
var pairs = lines.SkipWhile(l => l.Text != "Practice 名称").Pairs();
foreach(var pair in pairs)
    Console.WriteLine($"{pair.Key}: {pair.Value}");
似乎对我来说是对的。
 

WeyardWiz

会员
已加入
2020年10月23日
留言内容
23
编程经验
3-5
Flip the logic.
C#:
var pairs = lines.SkipWhile(l => l.Text != "Practice 名称").Pairs();
foreach(var pair in pairs)
    Console.WriteLine($"{pair.Key}: {pair.Value}");
似乎对我来说是对的。
太棒了,确实可以解决问题 :)
顺便说一句,此JSON结构是通过以下方式生成的 Azure计算机视觉REST API 从这样的pdf输入中:

1603905939908.png


我之所以这样说,是因为我了解IEnumerable代码在做什么,但是有一种极端情况可能与它的工作方式不符。基本上,我的理解是:

扫描JSON似乎表明奇数行的.text是字段的名称
偶数行的.text是该字段的值。
例如:
如果lines [3] .text是"Owner Full 名称",
那么第[3 + 1]行是"Bob Lee"

跳过的变量将是感兴趣区域之前的所有内容的“行”输入
删除。然后,我们仅跳过字段名称行并返回下一行的.text属性。

API将图片/ pdf中的完整JSON导出为:

JSON:
{
  "status": "succeeded",
  "createdDateTime": "2020-10-22T19:35:35Z",
  "lastUpdatedDateTime": "2020-10-22T19:35:36Z",
  "analyzeResult": {
    "version": "3.0.0",
    "readResults": [
      {
        "page": 1,
        "angle": 0,
        "width": 8.5,
        "height": 11,
        "unit": "inch",
        "lines": [       
          {
            "boundingBox": [
              0.5016,
              1.9141,
              2.5726,
              1.9141,
              2.5726,
              2.0741,
              0.5016,
              2.0741
            ],         
           "text": "Account Information",
            "words": [
              {
                "boundingBox": [
                  0.5016,
                  1.9345,
                  1.3399,
                  1.9345,
                  1.3399,
                  2.0741,
                  0.5016,
                  2.0741
                ],
                "text": "Account",
                "confidence": 1
              },
              {
                "boundingBox": [
                  1.3974,
                  1.9141,
                  2.5726,
                  1.9141,
                  2.5726,
                  2.0741,
                  1.3974,
                  2.0741
                ],
                "text": "Information",
                "confidence": 1
              }
            ]
          },
          {
            "boundingBox": [
              1.7716,
              2.4855,
              2.8793,
              2.4855,
              2.8793,
              2.6051,
              1.7716,
              2.6051
            ],
            "text": "Practice 名称",
            "words": [
              {
                "boundingBox": [
                  1.7716,
                  2.4855,
                  2.3803,
                  2.4855,
                  2.3803,
                  2.6051,
                  1.7716,
                  2.6051
                ],
                "text": "Practice",
                "confidence": 1
              },
              {
                "boundingBox": [
                  2.4362,
                  2.4948,
                  2.8793,
                  2.4948,
                  2.8793,
                  2.6051,
                  2.4362,
                  2.6051
                ],
                "text": "Name",
                "confidence": 1
              }
            ]
          },
          {
            "boundingBox": [
              2.9993,
              2.5257,
              4.7148,
              2.5257,
              4.7148,
              2.714,
              2.9993,
              2.714
            ],
            "text": "Some Practice 名称",
            "words": [
              {
                "boundingBox": [
                  3.0072,
                  2.5385,
                  3.6546,
                  2.5284,
                  3.6516,
                  2.7131,
                  3.0105,
                  2.712
                ],
                "text": "Some",
                "confidence": 0.984
              },
              {
                "boundingBox": [
                  3.6887,
                  2.5281,
                  4.2112,
                  2.5262,
                  4.2028,
                  2.7159,
                  3.6854,
                  2.7132
                ],
                "text": "Practice",
                "confidence": 0.986
              },
              {
                "boundingBox": [
                  4.2453,
                  2.5263,
                  4.7223,
                  2.5297,
                  4.7091,
                  2.72,
                  4.2366,
                  2.7161
                ],
                "text": "Name",
                "confidence": 0.986
              }
            ]
          },
          {
            "boundingBox": [
              1.6116,
              2.9999,
              2.8816,
              2.9999,
              2.8816,
              3.1158,
              1.6116,
              3.1158
            ],
            "text": "Owner Full 名称",
            "words": [
              {
                "boundingBox": [
                  1.6116,
                  3.0039,
                  2.1026,
                  3.0039,
                  2.1026,
                  3.1157,
                  1.6116,
                  3.1157
                ],
                "text": "Owner",
                "confidence": 1
              },
              {
                "boundingBox": [
                  2.1541,
                  2.9999,
                  2.3784,
                  2.9999,
                  2.3784,
                  3.1158,
                  2.1541,
                  3.1158
                ],
                "text": "Full",
                "confidence": 1
              },
              {
                "boundingBox": [
                  2.4384,
                  3.0052,
                  2.8816,
                  3.0052,
                  2.8816,
                  3.1155,
                  2.4384,
                  3.1155
                ],
                "text": "Name",
                "confidence": 1
              }
            ]
          },
          {
            "boundingBox": [
              2.9993,
              3.0242,
              3.6966,
              3.0242,
              3.6966,
              3.2125,
              2.9993,
              3.2014
            ],
            "text": "Bob Lee",
            "words": [
              {
                "boundingBox": [
                  3.0063,
                  3.0303,
                  3.3439,
                  3.0349,
                  3.3461,
                  3.2125,
                  3.007,
                  3.2081
                ],
                "text": "Bob",
                "confidence": 0.987
              },
              {
                "boundingBox": [
                  3.3788,
                  3.0349,
                  3.6931,
                  3.0326,
                  3.697,
                  3.2121,
                  3.3813,
                  3.2125
                ],
                "text": "Lee",
                "confidence": 0.983
              }
            ]
          },
          {
            "boundingBox": [
              1.945,
              3.5063,
              2.8748,
              3.5063,
              2.8748,
              3.6261,
              1.945,
              3.6261
            ],
            "text": "Owner 电子邮件",
            "words": [
              {
                "boundingBox": [
                  1.945,
                  3.5143,
                  2.4359,
                  3.5143,
                  2.4359,
                  3.6261,
                  1.945,
                  3.6261
                ],
                "text": "Owner",
                "confidence": 1
              },
              {
                "boundingBox": [
                  2.4874,
                  3.5063,
                  2.8748,
                  3.5063,
                  2.8748,
                  3.6259,
                  2.4874,
                  3.6259
                ],
                "text": "Email",
                "confidence": 1
              }
            ]
          },
          {
            "boundingBox": [
              3.0104,
              3.5005,
              4.6042,
              3.5005,
              4.6042,
              3.6888,
              3.0104,
              3.6777
            ],
            "text": "[email protected]",
            "words": [
              {
                "boundingBox": [
                  3.0212,
                  3.5047,
                  4.5837,
                  3.5039,
                  4.5769,
                  3.6886,
                  3.0129,
                  3.6787
                ],
                "text": "[email protected]",
                "confidence": 0.951
              }
            ]
          },
          {
            "boundingBox": [
              1.945,
              6.5768,
              2.8886,
              6.5768,
              2.8886,
              6.7271,
              1.945,
              6.7271
            ],
            "text": "Server Setup",
            "words": [
              {
                "boundingBox": [
                  1.945,
                  6.5768,
                  2.4165,
                  6.5768,
                  2.4165,
                  6.6884,
                  1.945,
                  6.6884
                ],
                "text": "Server",
                "confidence": 1
              },
              {
                "boundingBox": [
                  2.4643,
                  6.5768,
                  2.8886,
                  6.5768,
                  2.8886,
                  6.7271,
                  2.4643,
                  6.7271
                ],
                "text": "Setup",
                "confidence": 1
              }
            ]
          },
          {
            "boundingBox": [
              3.5085,
              6.5025,
              3.7298,
              6.5136,
              3.7188,
              6.7351,
              3.4974,
              6.7241
            ],
            "text": "V",
            "words": [
              {
                "boundingBox": [
                  3.5672,
                  6.5046,
                  3.7293,
                  6.5128,
                  3.7183,
                  6.734,
                  3.5561,
                  6.7259
                ],
                "text": "V",
                "confidence": 0.984
              }
            ]
          },
          {
            "boundingBox": [
              3.7471,
              6.6145,
              4.1792,
              6.6145,
              4.1792,
              6.7304,
              3.7471,
              6.7304
            ],
            "text": "Cloud",
            "words": [
              {
                "boundingBox": [
                  3.7471,
                  6.6145,
                  4.1792,
                  6.6145,
                  4.1792,
                  6.7304,
                  3.7471,
                  6.7304
                ],
                "text": "Cloud",
                "confidence": 1
              }
            ]
          },
          {
            "boundingBox": [
              4.904,
              6.6105,
              5.5344,
              6.6105,
              5.5344,
              6.7301,
              4.904,
              6.7301
            ],
            "text": "Location",
            "words": [
              {
                "boundingBox": [
                  4.904,
                  6.6105,
                  5.5344,
                  6.6105,
                  5.5344,
                  6.7301,
                  4.904,
                  6.7301
                ],
                "text": "Location",
                "confidence": 1
              }
            ]
          },
          {
            "boundingBox": [
              6.2924,
              6.6037,
              7.8618,
              6.6037,
              7.8618,
              6.752,
              6.2924,
              6.752
            ],
            "text": "Central (multi-location)",
            "words": [
              {
                "boundingBox": [
                  6.2924,
                  6.6145,
                  6.8385,
                  6.6145,
                  6.8385,
                  6.7301,
                  6.2924,
                  6.7301
                ],
                "text": "Central",
                "confidence": 1
              },
              {
                "boundingBox": [
                  6.8929,
                  6.6037,
                  7.8618,
                  6.6037,
                  7.8618,
                  6.752,
                  6.8929,
                  6.752
                ],
                "text": "(multi-location)",
                "confidence": 1
              }
            ]
          },
          {
            "boundingBox": [
              0.6466,
              7.0788,
              2.8775,
              7.0788,
              2.8775,
              7.2388,
              0.6466,
              7.2388
            ],
            "text": "Number of 地点s Enrolling",
            "words": [
              {
                "boundingBox": [
                  0.6466,
                  7.0832,
                  1.2496,
                  7.0832,
                  1.2496,
                  7.1991,
                  0.6466,
                  7.1991
                ],
                "text": "Number",
                "confidence": 1
              },
              {
                "boundingBox": [
                  1.2969,
                  7.0788,
                  1.4364,
                  7.0788,
                  1.4364,
                  7.1988,
                  1.2969,
                  7.1988
                ],
                "text": "of",
                "confidence": 1
              },
              {
                "boundingBox": [
                  1.4892,
                  7.0793,
                  2.2013,
                  7.0793,
                  2.2013,
                  7.1988,
                  1.4892,
                  7.1988
                ],
                "text": "Locations",
                "confidence": 1
              },
              {
                "boundingBox": [
                  2.2576,
                  7.0793,
                  2.8775,
                  7.0793,
                  2.8775,
                  7.2388,
                  2.2576,
                  7.2388
                ],
                "text": "Enrolling",
                "confidence": 1
              }
            ]
          },
          {
            "boundingBox": [
              3.4421,
              7.0342,
              3.6413,
              7.0453,
              3.6413,
              7.3001,
              3.4421,
              7.289
            ],
            "text": "1",
            "words": [
              {
                "boundingBox": [
                  3.4757,
                  7.0352,
                  3.6451,
                  7.0446,
                  3.631,
                  7.299,
                  3.4616,
                  7.2896
                ],
                "text": "1",
                "confidence": 0.987
              }
            ]
          },
          {
            "boundingBox": [
              4.1835,
              7.0896,
              7.8999,
              7.0896,
              7.8999,
              7.2158,
              4.1835,
              7.2158
            ],
            "text": "*If more than 1 location, add info on the locations form",
            "words": [
              {
                "boundingBox": [
                  4.1835,
                  7.0896,
                  4.3291,
                  7.0896,
                  4.3291,
                  7.1979,
                  4.1835,
                  7.1979
                ],
                "text": "*If",
                "confidence": 1
              },
              {
                "boundingBox": [
                  4.3611,
                  7.1193,
                  4.725,
                  7.1193,
                  4.725,
                  7.1988,
                  4.3611,
                  7.1988
                ],
                "text": "more",
                "confidence": 1
              },
              {
                "boundingBox": [
                  4.7701,
                  7.0936,
                  5.0809,
                  7.0936,
                  5.0809,
                  7.1988,
                  4.7701,
                  7.1988
                ],
                "text": "than",
                "confidence": 1
              },
              {
                "boundingBox": [
                  5.1307,
                  7.0985,
                  5.1613,
                  7.0985,
                  5.1613,
                  7.1979,
                  5.1307,
                  7.1979
                ],
                "text": "1",
                "confidence": 1
              },
              {
                "boundingBox": [
                  5.2006,
                  7.09,
                  5.7803,
                  7.09,
                  5.7803,
                  7.2158,
                  5.2006,
                  7.2158
                ],
                "text": "location,",
                "confidence": 1
              },
              {
                "boundingBox": [
                  5.8268,
                  7.0936,
                  6.102,
                  7.0936,
                  6.102,
                  7.1988,
                  5.8268,
                  7.1988
                ],
                "text": "add",
                "confidence": 1
              },
              {
                "boundingBox": [
                  6.1394,
                  7.0896,
                  6.3896,
                  7.0896,
                  6.3896,
                  7.1988,
                  6.1394,
                  7.1988
                ],
                "text": "info",
                "confidence": 1
              },
              {
                "boundingBox": [
                  6.435,
                  7.1193,
                  6.6005,
                  7.1193,
                  6.6005,
                  7.1988,
                  6.435,
                  7.1988
                ],
                "text": "on",
                "confidence": 1
              },
              {
                "boundingBox": [
                  6.6481,
                  7.0936,
                  6.865,
                  7.0936,
                  6.865,
                  7.1988,
                  6.6481,
                  7.1988
                ],
                "text": "the",
                "confidence": 1
              },
              {
                "boundingBox": [
                  6.9081,
                  7.09,
                  7.5365,
                  7.09,
                  7.5365,
                  7.1988,
                  6.9081,
                  7.1988
                ],
                "text": "locations",
                "confidence": 1
              },
              {
                "boundingBox": [
                  7.5783,
                  7.0896,
                  7.8999,
                  7.0896,
                  7.8999,
                  7.1988,
                  7.5783,
                  7.1988
                ],
                "text": "form",
                "confidence": 1
              }
            ]
          }
        ]
      }
    ]
  }
}

我认为该API并不完美,因此在边界框中涉及多个元素时,我们会遇到一些麻烦。例如,API的解释方式"Server Setup"和它解释的一样"Owner Full 名称",基本上只是遵循这样的约定:奇数行的.text是字段的名称,偶数行的.text是该字段的值。
它无法放置所谓的"values"那个领域的"inner"内的有界框"Server Setup"文本,因此我们最终得到这样的输出:

Practice 名称: Some Practice 名称
所有者全名: 鲍勃·李
所有者电子邮件: [email protected]
服务器设置: V
云:位置
Central (multi-location): 地点数 Enrolling
1:*如果位置不止一个,请在位置表格中添加信息

While Practice 名称, Owner, Full 名称, 和 Owner 电子邮件 fields/values are correct, the 服务器设置 field 和 价值观 unfortunately is not. 和 that is understandable because the JSON structure is like that to begin with, missing a "child"类元素的依赖关系,否则我们会在pdf / image中观察到。

1603906337179.png


注意:"V"表示该复选标记,因为该API似乎无法将符号解释为JSON。

但是理想的输出应该是这样的:

Practice 名称: Some Practice 名称
所有者全名: 鲍勃·李
所有者电子邮件: [email protected]
服务器设置: Cloud
位置:中央(多位置)
地点数 Enrolling: 1

如何调整IEnumerable代码以适应这种边缘情况(如果可能的话)?
 

跳伞

工作人员
已加入
2019年4月6日
留言内容
2,497
地点
弗吉尼亚州切萨皮克
编程经验
10+
回想一下帖子8,我说:
If you know that each pair of lines is always a name-value pair, then you can just ingest the lines in pairs 和 setup the 价值观 to go out into the CSV.

您的数据不符合该条件。

花时间阅读有关LINQ流水线和流畅接口如何工作的信息。您可以添加额外的过滤器和修饰符,以更改数据沿管道向下流动的方式,并尝试调整字段的枚举。

就我个人而言,我认为您使用错误的方法先执行OCR,然后再尝试对输出的数据进行处理。我的建议是先对扫描的PDF或纸张进行AI分类,然后将不同形式的表格分类为特定类型的存储桶。然后,对于每个存储桶,您将应用“策略”模式,并具有一个与OCR一起使用的自定义掩码,以仅扫描对您重要的数据。然后,当每个存储桶中的数据出来时,它会被馈入POCO,这是您最终希望保存到CSV的正确数据形状。我的直觉说,您必须以任何一种方式走这条路,因为在某些形式可能会说出的地方会有差异"Owner Full 名称",而其他形式将"Owner's 名称", or just "Name". And other forms may have the different fields in different orders (and so that SkipWhile() will end up skipping over important data. Consider what happens when you have to deal with languages that are RTL, where the field labels will be on the right 和 the 价值观 will be on the left.
 

WeyardWiz

会员
已加入
2020年10月23日
留言内容
23
编程经验
3-5
您的数据不符合该条件。

花时间阅读有关LINQ流水线和流畅接口如何工作的信息。您可以添加额外的过滤器和修饰符,以更改数据沿管道向下流动的方式,并尝试调整字段的枚举。
因为有些表格可能会说出差异"Owner Full 名称",而其他形式将"Owner's 名称", or just "Name". And other forms may have the different fields in different orders (and so that SkipWhile() will end up skipping over important data. Consider what happens when you have to deal with languages that are RTL, where the field labels will be on the right 和 the 价值观 will be on the left.
这是非常好的一点。 Ive与团队进行了审查,他们说此表格将是官方模板,因此我们不必担心差异。
Since that's the case, does the desired output im seeking from the JSON still not meet the condition in post#8? In other words, the above code could only work for JSON items meeting that condition, like 所有者全名?
 

跳伞

工作人员
已加入
2019年4月6日
留言内容
2,497
地点
弗吉尼亚州切萨皮克
编程经验
10+
即使没有差异,数据仍然不满足相邻线对彼此相关的条件。的"Server Setup"后面紧接4条与之相关的线。的"Number of 地点s"有2条线与此相关。
 

约翰·H

C#论坛主持人
工作人员
已加入
2011年4月23日
留言内容
1,028
地点
挪威
编程经验
10+
也许尝试按boundingBox中的第二个数字(似乎是线Y坐标)将线分组,则需要+ -0.12的接近度比较,请参见 LINQ(或伪代码)按接近程度对项目进行分组
然后,您可以处理每个组,其中第一个文本为标签,第二个为值。的"Server Setup"该行将需要特殊处理,以找出跟随"V" selection.
 

约翰·H

C#论坛主持人
工作人员
已加入
2011年4月23日
留言内容
1,028
地点
挪威
编程经验
10+
按照我的建议,这增加了 @跳伞在第10页中的代码。
Line class:
[JsonProperty("boundingBox")]
public double[] BoundingBox { get; set; }
IEnumerableExtensions:
internal static IEnumerable<IEnumerable<Line>> GroupByProximity(this IEnumerable<Line> source, double threshold)
{
    var g = new 清单<Line>();
    foreach (var x in source)
    {
        if ((g.Count != 0) && (!x.BoundingBox[1].IsProximity(g[0].BoundingBox[1], threshold)))
        {
            yield return g;
            g = new 清单<Line>();
        }
        g.Add(x);
    }
    yield return g;
}

private static bool IsProximity(this double value, double compareTo, double treshold) {
    return value >= compareTo - treshold && value <= compareTo + treshold;
}
example usage:
var lines = GetLines(File.ReadAllText("response.json"));
var groups = lines.GroupByProximity(0.12);

var dictionary = groups.ToDictionary(g => g.First().Text, g => g.Skip(1).Select(line => line.Text));
var value1 = dictionary["Practice 名称"].First();
var value2 = dictionary["Server Setup"].SkipWhile(s => s != "V").Skip(1).FirstOrDefault();
var value3 = string.Join(" ", dictionary["Number of 地点s Enrolling"]);
ToDictionary要求标签是不同的,如果不是,则可以使用ToLookup。
value2 example不允许选择,在这种情况下将为null。
value3 is just an example combining all line 价值观 to a single string.
 
最佳 底部