A method of combining serialization with parsing grammar?

I have a dilemma. My C # application uses a custom file format that must be editable in a text editor, but can also be editable via the graphical interface in my application. This file will be a top-level object (name it TopObject), which contains several smaller objects, which, in turn, contain other objects, etc. All data contained in these objects is contained in a file.

I am stuck how to solve the problem of loading / saving these files. C # serialization doesn't work for me because it violates the likelihood (binary serialization) or has β€œproblems” with serializing collections of base classes (XML serialization and DataContract, which add text to eliminate ambiguous derived classes when serializing a base class that makes files more fragile for human editing); if there was no need to edit files manually, it would be a ticket. I studied parser generators such as GOLD and GPLEX / GPPG to analyze and convert the file into the objects they represent, and looks promising, but this only applies to one direction of file loading, not guaranteeing that they are saved in the correct format when they are written .

What would be great would be to indicate a grammar that handles both:
1) Reading a file with the specified structure and converting it to a TopObject and all its contained objects and
2) Given the TopObject, writing its state to a file with the same structure.
To a large extent, the only grammar that provides the import structure, as well as the output structure.

Are there any tools or frameworks that could help me? Is this something possible, or am I thinking too much about it, and is there an easier way?

+4
source share
2 answers

I would still use XML, but just write my own serializer. You can use the XML read / write classes in .Net to create a simple XML format:

<TopObject> <SubObject> <SubObject> etc. </SubObject> <SubObject> etc. </SubObject> </SubObject> <SubObject></SubObject> </TopObject> 

I don’t know if you think this is understandable enough for a person, but better than creating a .Net serializer. It would be easy to read / write recursively.

Example:

Here is a simplified example that you can adapt. Suppose I have this class:

 public class Node { public Node(String _SomeProperty) { this.SomeProperty = _SomeProperty; } public String SomeProperty; public List<Node> Children = new List<Node>(); } 

Each Node has a property called SomeProperty . He may also have children; more Nodes in the Children property.

Here is the main from the Console application that creates some data from this class for serialization:

 static void Main(string[] args) { // Make some data for testing Node baseObject = new Node("This is the base class"); List<Node> Children = new List<Node>(){ new Node("This is a child"), new Node("This is another child") }; baseObject.Children = Children; Node aSubChild = new Node("This is a child of a child"); baseObject.Children[0].Children = new List<Node>() { aSubChild }; // Serialize XmlWriter writer = XmlWriter.Create("test.xml"); writer.WriteStartDocument(); RecursivelySerialize(ref writer, baseObject); writer.Flush(); } 

It calls a method called RecursivelySerialize , which does this actual work:

 private static void RecursivelySerialize(ref XmlWriter writer, Node sc) { writer.WriteStartElement("Node"); writer.WriteElementString("SomeProperty", sc.SomeProperty); if (sc.Children.Count > 0) { writer.WriteStartElement("Nodes"); foreach (Node scChild in sc.Children) RecursivelySerialize(ref writer, scChild); writer.WriteEndElement(); } writer.WriteEndElement(); } 

This method is not complicated. To improve it, you can use Reflection to dynamically serialize any type of class. Here is the result I got (formatted nicely) when running the above code:

 <?xml version="1.0" encoding="utf-8"?> <Node> <SomeProperty>This is the base class</SomeProperty> <Nodes> <Node> <SomeProperty>This is a child</SomeProperty> <Nodes> <Node> <SomeProperty>This is a child of a child</SomeProperty> </Node> </Nodes> </Node> <Node> <SomeProperty>This is another child</SomeProperty> </Node> </Nodes> </Node> 
+4
source

Personally, I would not dwell on making the file accessible to humans, at least not editable by non-technical people. If an application needs to consume a file, then it will require accuracy, and no matter what grammar you install, people will still get it wrong.

XML / JSON / INI is still hard for some tech people not to mess up (surprisingly), but at least they are familiar with some techniques. I think this is a better choice than casting your own grammar. Even better, if you want to make editing the file more convenient for the user, you can consider abandoning the "human-editable" and make it available only for the application.

+1
source

Source: https://habr.com/ru/post/1338191/


All Articles