C#Text Parser就像GraphQL一样

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C#Text Parser就像GraphQL一样相关的知识,希望对你有一定的参考价值。

我试图在C#中分割出以下格式,并且在循环中变得很糟糕。

{
  books{
    isbn
    name
    author{
      id
      name
      birthdate
    }
  }
}

我本质上希望能够识别像书籍和作者这样的关键对象,其中isbn,name,id等属于该对象的属性,同时也知道在这种情况下,作者链接到该书有可能像发布者这样的东西也可以作为书籍的子对象。

关于如何做到这一点的任何线索。我一直在完成所有循环并且无法正确分组。

答案

有很多方法可以处理解析。你可以使用词法分析器,你可以使用解析器组合器。

在这种情况下,我会写一个简单的递归下降解析器。您基本上必须跟踪打开和关闭大括号,并随时创建对象树。

通过调用GraphObject.Read(inputString)解析你的字符串。您可以在this dotnetfiddle上试用此代码。

// A object can have to kinds of properties, simple values or sub-objects
public enum GraphElementType {
    @Object,    
    Value
}

// To make it easy to keep all values and objects in order, we define a single base class for both
// We define all elements to have a name, and set a static name for the root element
public abstract class GraphElement
{
    public static readonly string ROOT_NAME = "<ROOT>";

    public GraphElementType ElementType { get; }
    public string Name {get;}

    protected GraphElement(GraphElementType type, string name) {
        ElementType = type;
        Name = name;
    }
}

public class GraphValue : GraphElement
{
    public GraphValue(string name) : base(GraphElementType.Value, name) { }
}

public class GraphObject : GraphElement {   
    public List<GraphElement> Properties {get;} = new List<GraphElement>();

    public GraphObject(string name) : base(GraphElementType.Object, name) { }


    public static GraphObject Read(string graphString)
    {
        return Read(new StringReader(graphString));
    }

    public static GraphObject Read(TextReader reader)
    {
        var root = Read(GraphElement.ROOT_NAME, reader);        
        if(ConsumeWhitespaceAndPeek(reader) != -1) {
            throw new ApplicationException("Unexpected content after root object");
        }       
        return root;
    }

    // Read an object with the given name from the given reader.
    // The reader must be positioned at the opening brace of the object.
    protected static GraphObject Read(string name, TextReader reader)
    {
        // Consume opening '{'
        if (reader.Read() != '{') throw new ApplicationException("Invalid object start");

        var o = new GraphObject(name);      
        while(true)
        {
            var next = ConsumeWhitespaceAndPeek(reader);
            if (next == -1) throw new ApplicationException("Unexpected end of input, unclosed object");

            if (next == '}')  {
                reader.Read(); // consume closing '}'
                return o;
            }

            var str = ConsumeUntilWhitespaceOrBrace(reader);
            next = ConsumeWhitespaceAndPeek(reader);         

            if (str.Length > 0 && next  == '{')
            {
                o.Properties.Add(Read(str, reader));
            }
            else if (str.Length > 0)
            {
                o.Properties.Add(new GraphValue(str));
            }
        }
    }
    // Helper method: Collect all non-whitespace, non-brace characters into a string
    private static string ConsumeUntilWhitespaceOrBrace(TextReader reader) {
        var b = new StringBuilder();

        var next = reader.Peek();
        while (next != -1 && !Char.IsWhiteSpace((char)next) && next != '}' && next != '{') {
            b.Append((char)next);
            reader.Read();
            next = reader.Peek();
        }

        return b.ToString();
    }

    // Helper method: Advance reader past any whitespace
    private static int ConsumeWhitespaceAndPeek(TextReader reader) {
        var next = reader.Peek();
        while(next != -1 && Char.IsWhiteSpace((char)next)) {
            reader.Read();
            next = reader.Peek();
        }

        return next;
    }
}

以上是关于C#Text Parser就像GraphQL一样的主要内容,如果未能解决你的问题,请参考以下文章

GraphQL - 缺少 POST 正文。你忘记使用 body-parser 中间件了吗?

Nestjs graphql 上传错误:缺少 POST 正文。你忘记使用 body-parser 中间件了吗?

异常Maxwell异常 Exception in thread "main" net.sf.jsqlparser.parser.TokenMgrError: Lexical e(代

node----DeprecationWarning: current URL string parser is deprecated和Port 3000 is already in use的问题(代

为啥 json-parser 解析错误我的 json

使用 graphql 查询连接 3 个表