8

I'm looking to convert between a YAML file, and JSON. This was really difficult to find any information on.

dimo414
  • 47,227
  • 18
  • 148
  • 244
Michael Brown
  • 1,585
  • 1
  • 22
  • 36
  • 1
    Do you want to preserve all of the YAML information (such as typing, anchors/references, comments, block vs flow style, multiline scalars)? Or do you just want to dump some internal object representation that was at some point deserialized from YAML in some form, and don't care about loosing most of the information in the YAML file (maybe because you're dealing with extremely simple YAML files)? – Anthon May 21 '15 at 06:02

3 Answers3

17

If you do not need the features of Json.NET, you can also use the Serializer class directly to emit JSON:

// now convert the object to JSON. Simple!
var js = new Serializer(SerializationOptions.JsonCompatible);

var w = new StringWriter();
js.Serialize(w, o);
string jsonText = w.ToString();

You can check two working fiddles here:

Antoine Aubry
  • 12,203
  • 10
  • 45
  • 74
  • 1
    What does the `o` relate to in this code snippet? – PontiusTheBarbarian Dec 14 '20 at 17:35
  • 1
    If you change `scalar` from `a scalar` to number like `100500` it will be "100500" in output with quotes instead of pure 100500. How to preserve original values of unknown in advance yaml? – Slava Utesinov Oct 16 '21 at 12:51
  • 1
    @PontiusTheBarbarian I believe options that are specified elsewhere (like formatting, etc. see https://learn.microsoft.com/en-us/dotnet/standard/serialization/system-text-json/how-to?pivots=dotnet-8-0#serialization-behavior) but OP should definitely clarify/update their post to show what `o` is declared as. – TylerH Jun 01 '23 at 13:38
6

It is possible to do this by using the built-in JSON library along with YamlDotNet. It wasn't apparent in the YamlDotNet documentation, but I found a way to do it rather simply.

// convert string/file to YAML object
var r = new StreamReader(filename); 
var deserializer = new Deserializer(namingConvention: new CamelCaseNamingConvention());
var yamlObject = deserializer.Deserialize(r);

// now convert the object to JSON. Simple!
Newtonsoft.Json.JsonSerializer js = new Newtonsoft.Json.JsonSerializer();

var w = new StringWriter();
js.Serialize(w, yamlObject);
string jsonText = w.ToString();

I was surprised this worked as well as it did! JSON output was identical to other web based tools.

Austin
  • 105
  • 1
  • 12
Michael Brown
  • 1,585
  • 1
  • 22
  • 36
0

Complete code examples using YamlDotNet.Serialization below. The examples are with object to YAML string and YAML string to an object. You can then easily serialize and deserialize (marshal and unmarshal) JSON in .NET.

Example using built in System.Text.Json:

https://learn.microsoft.com/en-us/dotnet/standard/serialization/system-text-json/how-to?pivots=dotnet-7-0#serialization-example

If you want a base serializer for YAML in .NET runtime you can vote for that here:

https://github.com/dotnet/runtime/issues/83313

However as @davidfowl on the ASP.NET team points out:

https://www.nuget.org/packages/YamlDotNet is the defacto YAML implementation for .NET

https://github.com/dotnet/runtime/issues/83313#issuecomment-1467411353

using System;
using System.Collections.Generic;
using YamlDotNet.Serialization;
using YamlDotNet.Serialization.NamingConventions;

public class Address
{
    public string Street { get; set; }
    public string City { get; set; }
    public string State { get; set; }
    public string Zip { get; set; }
}

public class Person
{
    public string Name { get; set; }
    public int Age { get; set; }
    public float HeightInInches { get; set; }
    public Dictionary<string, Address> Addresses { get; set; }

}
   
public class Program
{
    public static void Main()
    {
        var person = new Person
        {
            Name = "Abe Lincoln",
            Age = 25,
            HeightInInches = 6f + 4f / 12f,
            Addresses = new Dictionary<string, Address>{
                { "home", new  Address() {
                        Street = "2720  Sundown Lane",
                        City = "Kentucketsville",
                        State = "Calousiyorkida",
                        Zip = "99978",
                    }},
                { "work", new  Address() {
                        Street = "1600 Pennsylvania Avenue NW",
                        City = "Washington",
                        State = "District of Columbia",
                        Zip = "20500",
                    }},
            }
        };

        var serializer = new SerializerBuilder()
            .WithNamingConvention(CamelCaseNamingConvention.Instance)
            .Build();
        var yaml = serializer.Serialize(person);
        System.Console.WriteLine(yaml);
        // Output: 
        // name: Abe Lincoln
        // age: 25
        // heightInInches: 6.3333334922790527
        // addresses:
        //   home:
        //     street: 2720  Sundown Lane
        //     city: Kentucketsville
        //     state: Calousiyorkida
        //     zip: 99978
        //   work:
        //     street: 1600 Pennsylvania Avenue NW
        //     city: Washington
        //     state: District of Columbia
        //     zip: 20500

        var yml = @"
name: George Washington
age: 89
height_in_inches: 5.75
addresses:
  home:
    street: 400 Mockingbird Lane
    city: Louaryland
    state: Hawidaho
    zip: 99970
";

        var deserializer = new DeserializerBuilder()
            .WithNamingConvention(UnderscoredNamingConvention.Instance)
            .Build();

        //yaml contains a string containing your YAML
        var p = deserializer.Deserialize<Person>(yml);
        var h = p.Addresses["home"];
        System.Console.WriteLine($"{p.Name} is {p.Age} years old and lives at {h.Street} in {h.City}, {h.State}.");
        // Output:
        // George Washington is 89 years old and lives at 400 Mockingbird Lane in Louaryland, Hawidaho.

    }
}

Source:

https://dotnetfiddle.net/CQ7ZKi

https://github.com/aaubry/YamlDotNet

Ogglas
  • 62,132
  • 37
  • 328
  • 418