how to serialize a YamlDocument to yaml string - c#

I use YamlDotnet and I have a YamlDocument. Now I want to convert it to his yaml text representation in memory but I don't see how to achieve that.
var yaml = new YamlDocument(new YamlMappingNode());
yaml.Add("one", "other")
var text = yaml.ToYamlText()
and I should get in text something like :
one: "other"
I tried zith Serializer class but with no success

ok so I found the solution in unit test of the source code :
var yaml = new YamlDocument(new YamlMappingNode());
yaml.Add("one", "other");
var yamlStream = new YamlStream(yaml);
var buffer = new StringBuilder();
using (var writer = new StringWriter(buffer))
{
yamlStream.Save(writer);
yamlText = writer.ToString();
}
Anyway, I have now another problem, I need all my values to be surrounded by double quotes. In another application I was using a QuoteSurroundingEventEmitter : ChainedEventEmitter with an object graph selrialization. But with yamlStream.Save() I don't see how to implement this mecanism

Related

Deserialize object one by one from file .Net

I'm trying to deserialize a list of heavy objects from a json file. I do not want to deserialize it the classic way, like directly to a list, because it will expose me to an OutOfMemory exception. So I'm looking for a way to handle object one by one to store them one by one in the database and be memory safe.
I already handle the serialization and it's working well, but I'm facing some difficulties for deserialization.
Any idea ?
Thanks in advance
// Serialization
using (var FileStream = new FileStream(DirPath + "/TPV.Json", FileMode.Create))
{
using (var sw = new StreamWriter(FileStream))
{
using (var jw = new JsonTextWriter(sw))
{
jw.WriteStartArray();
using (var _Database = new InspectionBatimentsDataContext(TheBrain.DBClient.ConnectionString))
{
foreach (var TPVId in TPVIds)
{
var pic = (from p in _Database.TPV
where Operators.ConditionalCompareObjectEqual(p.Release, TPVId.Release, false) & Operators.ConditionalCompareObjectEqual(p.InterventionId, TPVId.InterventionId, false)
select p).FirstOrDefault;
var ser = new JsonSerializer();
ser.Serialize(jw, pic);
jw.Flush();
}
}
jw.WriteEndArray();
}
}
}
I finnaly found a way to do it by using custom separator beetween each object during serialization. Then for deserialization, I simply read the json file as string until I find my custom separator and I deserialise readed string, all in a loop. It's not the perfect answer because I'm breaking json format in my files, but it's not a constraint in my case.

Get the JSON Schema's from a large OpenAPI Document OR using NewtonSoft and resolve refs

I'm currently looking extracting all of the JSON Schemas from a large OpenAPI spec. I've been using the following NuGet packages:
Microsoft.OpenApi v1.3.1
Microsoft.OpenApi.Readers v1.3.1
I was hoping to use these to parse a large Open API spec and extract all of the JSON Schemas, which I am able to parse into 'Microsoft.OpenApi.Models.OpenApiSchema' objects. But I can't seem to create a JSON Schema from these objects and write it to file.
As it stands at the moment I have the following:
using (FileStream fs = File.Open(file.FullName, FileMode.Open))
{
var openApiDocument = new OpenApiStreamReader().Read(fs, out var diagnostic);
foreach (var schema in openApiDocument.Components.Schemas)
{
var schemaName = schema.Key;
var schemaContent = schema.Value;
var outputDir = Path.Combine(outputDirectory.FullName, fileNameWithoutExtension);
if (!Directory.Exists(outputDir))
{
Directory.CreateDirectory(outputDir);
}
var outputPath = Path.Combine(outputDir, schemaName + "-Schema.json");
var outputString = schemaContent.Serialize(OpenApiSpecVersion.OpenApi3_0, OpenApiFormat.Json);
using (TextWriter sw = new StreamWriter(outputPath, true))
{
sw.Write(outputString);
sw.Close();
}
}
}
The schemaContent appears to have all of the relevant properties for the schema, but I don't seem to be able to identify the next step in getting it from that object to a JSON Schema. I'm sure I'm missing something simple so any insight would be appreciated.
UPDATED
I had a bit of a think and took a slightly different approach using NewtonSoft Json instead.
var OpenApitext = File.ReadAllText(file.FullName, Encoding.UTF8);
var settings = new JsonSerializerSettings
{
PreserveReferencesHandling = PreserveReferencesHandling.Objects,
MetadataPropertyHandling = MetadataPropertyHandling.Ignore, //ign
Formatting = Newtonsoft.Json.Formatting.Indented
};
dynamic openApiJson = JsonConvert.DeserializeObject<ExpandoObject>(OpenApitext, settings);
if (openApiJson?.components?.schemas != null)
{
foreach (var schema in openApiJson.components.schemas)
{
var schemaString = JsonConvert.SerializeObject(schema, settings);
var outputDir = Path.Combine(outputDirectory.FullName, fileNameWithoutExtension);
if (!Directory.Exists(outputDir))
{
Directory.CreateDirectory(outputDir);
}
var outputPath = Path.Combine(outputDir, schema.Name + "-Schema.json");
using (TextWriter sw = new StreamWriter(outputPath, true))
{
sw.Write(schemaString);
sw.Close();
}
}
}
Now this will allow me to create the JSON Schema and write it to file, but it doesn't want to resolve references. Looking at the API spec all references appear to be local to the API Spec. What do I need to do in order to resolve all the references in the Open API Spec before I cycle through the schemas and write them to file? I've done a bit of research and a few people seem to build out this capability themselves, but they always use a class object as a way of supporting it which I can't do here.
I reached out through the microsoft/OpenAPI.NET GitHub repo in the end. By a bit of a coincidence/happenstance I got a response from the same person both there and here. So, thank you Darrel you've helped me solve the above scenario which I was getting rather confused over. I knew in the end it was that I hadn't quite implemented it correctly.
For reference the below use case was to take in a sizeable OpenAPI Spec (Json) and extract the JSON Schemas referenced whilst ensuring that the JSON Pointers ($ref, $id) etc were resolved when this was written out to file.
The reason this was the approach I wanted to take was that due to the size of the OpenAPI specs I had to work with it was incredibly difficult using pre-built tooling like Postman for example which can extract Schemas.
Final code snippet for my implementation, little rough on a couple of the lines, I'll neaten that up over the weekend.
Console.WriteLine($"Processing file: {file.FullName}");
var fileNameWithoutExtension = Path.GetFileNameWithoutExtension(file.FullName);
var fileExtension = Path.GetExtension(file.FullName);
var reader = new OpenApiStreamReader();
var result = await reader.ReadAsync(new FileStream(file.FullName, FileMode.Open));
foreach (var schemaEntry in result.OpenApiDocument.Components.Schemas)
{
var schemaFileName = schemaEntry.Key + ".json";
Console.WriteLine("Creating " + schemaFileName);
var outputDir = Path.Combine(outputDirectory.FullName, fileNameWithoutExtension);
if (!Directory.Exists(outputDir))
{
Directory.CreateDirectory(outputDir);
}
var outputPath = Path.Combine(outputDir, schemaFileName + "-Schema.json");
using FileStream? fileStream = new FileStream(outputPath, FileMode.CreateNew);
var writerSettings = new OpenApiWriterSettings() { InlineLocalReferences = true, InlineExternalReferences = true };
using var writer = new StreamWriter(fileStream);
schemaEntry.Value.SerializeAsV2WithoutReference(new OpenApiJsonWriter(writer, writerSettings));
}

Serializing a custom class to a file

I'm writing a save method for my Player class, I can serialize most fields using a binary writer however my custom class fields are not able to be serialized (i have a Race field for custom races)
Since I am going to have a lot of different custom classes - like Race - I really need a good reliable way of saving this information.
So, am I using the wrong kind of formatter? And if so, what is the one I should be using?
Alternatively, how do I write the method to serialize it? I have used the [Serializable()] attribute and implemented ISerializable interface where needed already.
Here is the code:
public void Save()
{
Stream stream = File.Open(SaveSlot, FileMode.Create);
BinaryWriter writer = new BinaryWriter(stream);
PlayerData saveData = new PlayerData();
writer.Write(saveData.Name = PlayerData.player.Name);
writer.Write(saveData.Race = PlayerData.player.Race);
writer.Write(saveData.PlayClass = PlayerData.player.PlayClass);
writer.Write(saveData.Level = PlayerData.player.Level);
writer.Write(saveData.Experience = PlayerData.player.Experience);
writer.Write(saveData.Strength = PlayerData.player.Strength);
writer.Write(saveData.Dexterity = PlayerData.player.Dexterity);
writer.Write(saveData.Constitution = PlayerData.player.Constitution);
writer.Write(saveData.Intelligence = PlayerData.player.Intelligence);
writer.Write(saveData.Wisdom = PlayerData.player.Wisdom);
writer.Write(saveData.Charisma = PlayerData.player.Charisma);
writer.Write(saveData.Wounds = PlayerData.player.Wounds);
writer.Write(saveData.MaxWounds = PlayerData.player.MaxWounds);
writer.Write(saveData.Attackbonus = PlayerData.player.Attackbonus);
writer.Write(saveData.Defensebonus = PlayerData.player.Defensebonus);
writer.Close();
Console.WriteLine("Data Saved Successfully");
}
Like I said in my comment you can use the json format for this.
Sample class
public class MyObject
{
public string MyProperty { get; set; }
}
Sample data
List<MyObject> objects = new List<MyObject>
{
new MyObject{MyProperty = "test 1"},
new MyObject{MyProperty = "test 2"},
new MyObject{MyProperty = "test 3"}
};
Sample code
Then you can use this code for serialize your data (using Newtonsoft).
string json = JsonConvert.SerializeObject(objects);
The content of json will be
[{"MyProperty":"test 1"},{"MyProperty":"test 2"},{"MyProperty":"test
3"}]
If you want to deserialize the string use this.
List<MyObject> deserialzed = JsonConvert.DeserializeObject<List<MyObject>>(json);
More info
You can save the json string to a file and load and deserialize it when you need it. This works with every type of a property including list and custom objects.
Have a read at the JSON format for more information.

Create variables from text file

I want to store variables in a .txt file - like I always see in peoples config.txt files, where it's like:
var_name = ['"test url"']
I've got the code below that opens the file and reads it (at the moment just debugging and displays what's in the file, at the moment just 1 variable)
System.IO.StreamReader myFile = new System.IO.StreamReader("C:\\conf\\config.txt");
string myString = myFile.ReadToEnd();
myFile.Close();
MessageBox.Show(myString);
What's in the file is
file_name="C:\\test.txt"
Now I'd like to be able to use that variable in my functions in my VB form. How do I go about doing this? And also, how can I do multiple; so I can have basically a big list of vars that the form loads at launch?
So for example:
// Opens file and reads all variables
// Saves all variables to form
// Can now use varaible in form, e.g. messageBox.Show(file_name);
I'm new to C#, I imagine it's similar to an include but the include is local instead of part of the project.
Disclamer: standard practice (i.e. Settings) usually is the best policy, however the question has been asked and can be asnwered:
I suggest using dictionary, e.g.
Dictionary<String, String> MySettings = File
.ReadLines(#"C:\conf\config.txt")
.ToDictionary(line => line.Substring(0, line.IndexOf('=')).Trim(),
line => line.Substring(line.IndexOf('=') + 1).Trim().Trim('"'));
...
String testUrl = MySettings[var_name];
However, if you prefer "variables" you can try ExpandoObject:
dynamic ExpSettings = new ExpandoObject();
var expandoDic = (IDictionary<string, object>) ExpSettings;
foreach (var pair in MySettings)
expandoDic.Add(pair.Key, pair.Value);
...
String testUrl = ExpSettings.var_name;
I store and load data (or variables) with Json Deserialization/ serialization in c#.
Here is Serialiazation: I make an object (postlist which is an object list) that i want to save in a text file That way:
private void save_file()
{
string path = Directory.GetCurrentDirectory() + #"\list.txt";
string json = JsonConvert.SerializeObject(postlist);
File.WriteAllText(path, json);
Application.Exit();
}
You need to install Newtonsoft.Json: http://www.newtonsoft.com/json
.You can do it with the Nuget tool console.
Don"t forget to use:
using Newtonsoft.Json;
Here is a way to get all your data from the text file, this is the deserialization:
private void read_file_list()
{
string line;
try
{
using (StreamReader sr = new StreamReader("list.txt"))
{
line = sr.ReadToEnd();
}
JsonSerializerSettings jsonSerializerSettings = new JsonSerializerSettings();
jsonSerializerSettings.MissingMemberHandling = MissingMemberHandling.Ignore;
postlist = JsonConvert.DeserializeObject<List<Post>>(line, jsonSerializerSettings);
}
catch
{
// catch your exception if you want
}
}
And here is how i store all my text in my object list "postlist".
Newtonsoft is very usefull and easy to use, i mostly use it to get data from api's.
This my first answer I hope it will help you.

Use Windows.Storage.ApplicationData object and his RoamingSettings property for save SerializableDictionary

In the code-behind of a page of Windows 8.1 app, I create a SerializableDictionary:
private static SerializableDictionary<string, Persona> elenco =
new SerializableDictionary<string, Persona>();
where, the SerializableDictionary class is this. How can I save elenco using Windows.Storage.ApplicationData object and his RoamingSettings property? (If it helps, even changing the declarations private static).
Well, since it's serializable, I guess one way would be to serialize it to a string and store that string in RoamingSettings. Something like this:
var stringBuilder = new StringBuilder();
var xmlWriter = XmlWriter.Create(stringBuilder);
elenco.WriteXml(xmlWriter);
var applicationData = Windows.Storage.ApplicationData.Current;
applicationData.RoamingSettings.Values["elenco"] = stringBuilder.ToString();
I haven't actually used RoamingSettings though, so I could be way off. Here's how you'd read the data back out:
var applicationData = Windows.Storage.ApplicationData.Current;
var elencoXml = (string)applicationData.RoamingSettings.Values["elenco"];
var xmlReader = XmlReader.Create(new StringReader(elencoXml));
elenco.ReadXml(xmlReader);

Categories

Resources