Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How do I specify the tag for each item in the List #765

Open
feelMySelfIsLouB opened this issue Jan 10, 2023 · 4 comments
Open

How do I specify the tag for each item in the List #765

feelMySelfIsLouB opened this issue Jan 10, 2023 · 4 comments
Labels

Comments

@feelMySelfIsLouB
Copy link

feelMySelfIsLouB commented Jan 10, 2023

My sample code:

class Person
{
    public int Age = 0;
    public string Name = string.Empty;
}
 public static void SerializePerson()
{
    List<Person> persons = new List<Person>();
    persons.Add(new Person { Age = 10, Name = "1" });
    persons.Add(new Person { Age = 20, Name = "2" });
    persons.Add(new Person { Age = 30, Name = "3" });
    persons.Add(new Person { Age = 40, Name = "4" });

    var serializer = new SerializerBuilder()
   .WithNamingConvention(CamelCaseNamingConvention.Instance)
   .WithTagMapping("person", typeof(Person))
   .Build();

    string yamContent = serializer.Serialize(persons);
    Console.WriteLine(yamContent);
}

Console.WriteLine result:

- person
    age: 10
    name: 1
- person
    age: 20
    name: 2
- person
    age: 30
    name: 3
- person
    age: 40
    name: 4

I want each item to have a different tag
just like this:

- person1
    age: 10
    name: 1
- person2
    age: 20
    name: 2
- person3
    age: 30
    name: 3
- person4
    age: 40
    name: 4

or tag uses an attribute of the Person class

What should I do to achieve this?Thank you!

@EdwardCooke
Copy link
Collaborator

That result is actually not valid YAML. Here's what the reference yaml parser returns for that (notice all the errors)
http://ben-kiki.org/ypaste/data/64377/index.html

I'm assuming you mean this (colons on the end):

- person1:
    age: 10
    name: 1
- person2:
    age: 20
    name: 2
- person3:
    age: 30
    name: 3
- person4:
    age: 40
    name: 4

In which case, this works:

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

namespace ConsoleApp1
{
    public static class TypeConverterExample1
    {
        public static void Test()
        {
            var personList = new List<Person?>
            {
                new Person() { Id = "person1", Age = 10, Name = "1" },
                new Person() { Id = "person2", Age = 20, Name = "2" },
                new Person() { Id = "person3", Age = 30, Name = "3" },
                new Person() { Id = "person4", Age = 40, Name = "4" },
                null
            };

            var serializer = new SerializerBuilder()
                .WithTypeConverter(new PersonTypeConverter())
                .Build();

            var yaml = serializer.Serialize(personList);
            Console.WriteLine(yaml);
        }

        private class PersonTypeConverter : IYamlTypeConverter
        {
            public bool Accepts(Type type) => type == typeof(Person);

            public object? ReadYaml(IParser parser, Type type)
            {
                throw new NotImplementedException();
            }

            public void WriteYaml(IEmitter emitter, object? value, Type type)
            {
                var person = (Person?)value;
                if (person == null)
                {
                    emitter.Emit(new YamlDotNet.Core.Events.Scalar("null"));
                    return;
                }
                emitter.Emit(new YamlDotNet.Core.Events.MappingStart(new AnchorName(), new TagName(), false, YamlDotNet.Core.Events.MappingStyle.Any));
                emitter.Emit(new YamlDotNet.Core.Events.Scalar(person.Id));

                emitter.Emit(new YamlDotNet.Core.Events.MappingStart(new AnchorName(), new TagName(), false, YamlDotNet.Core.Events.MappingStyle.Any));
                emitter.Emit(new YamlDotNet.Core.Events.Scalar("age"));
                emitter.Emit(new YamlDotNet.Core.Events.Scalar($"{person.Age}"));
                emitter.Emit(new YamlDotNet.Core.Events.Scalar("name"));
                emitter.Emit(new YamlDotNet.Core.Events.Scalar($"{person.Name}"));
                emitter.Emit(new YamlDotNet.Core.Events.MappingEnd());

                emitter.Emit(new YamlDotNet.Core.Events.MappingEnd());
            }
        }

        private class Person
        {
            public string Id { get; set; }
            public int Age { get; set; }
            public string Name { get; set; }
        }
    }
}

@feelMySelfIsLouB
Copy link
Author

该结果实际上不是有效的 YAML。以下是引用 yaml 解析器为此返回的内容(注意所有错误)http://ben-kiki.org/ypaste/data/64377/index.html

我假设你的意思是这个(末尾的冒号):

- person1:
    age: 10
    name: 1
- person2:
    age: 20
    name: 2
- person3:
    age: 30
    name: 3
- person4:
    age: 40
    name: 4

在这种情况下,这有效:

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

namespace ConsoleApp1
{
    public static class TypeConverterExample1
    {
        public static void Test()
        {
            var personList = new List<Person?>
            {
                new Person() { Id = "person1", Age = 10, Name = "1" },
                new Person() { Id = "person2", Age = 20, Name = "2" },
                new Person() { Id = "person3", Age = 30, Name = "3" },
                new Person() { Id = "person4", Age = 40, Name = "4" },
                null
            };

            var serializer = new SerializerBuilder()
                .WithTypeConverter(new PersonTypeConverter())
                .Build();

            var yaml = serializer.Serialize(personList);
            Console.WriteLine(yaml);
        }

        private class PersonTypeConverter : IYamlTypeConverter
        {
            public bool Accepts(Type type) => type == typeof(Person);

            public object? ReadYaml(IParser parser, Type type)
            {
                throw new NotImplementedException();
            }

            public void WriteYaml(IEmitter emitter, object? value, Type type)
            {
                var person = (Person?)value;
                if (person == null)
                {
                    emitter.Emit(new YamlDotNet.Core.Events.Scalar("null"));
                    return;
                }
                emitter.Emit(new YamlDotNet.Core.Events.MappingStart(new AnchorName(), new TagName(), false, YamlDotNet.Core.Events.MappingStyle.Any));
                emitter.Emit(new YamlDotNet.Core.Events.Scalar(person.Id));

                emitter.Emit(new YamlDotNet.Core.Events.MappingStart(new AnchorName(), new TagName(), false, YamlDotNet.Core.Events.MappingStyle.Any));
                emitter.Emit(new YamlDotNet.Core.Events.Scalar("age"));
                emitter.Emit(new YamlDotNet.Core.Events.Scalar($"{person.Age}"));
                emitter.Emit(new YamlDotNet.Core.Events.Scalar("name"));
                emitter.Emit(new YamlDotNet.Core.Events.Scalar($"{person.Name}"));
                emitter.Emit(new YamlDotNet.Core.Events.MappingEnd());

                emitter.Emit(new YamlDotNet.Core.Events.MappingEnd());
            }
        }

        private class Person
        {
            public string Id { get; set; }
            public int Age { get; set; }
            public string Name { get; set; }
        }
    }
}

Thank you very much. That's exactly what I wanted.

@feelMySelfIsLouB
Copy link
Author

How do I deserialize them with tag?
I tried to deserialize it directly, but I was told that Person does not have a person1 (tag, which is the Id value of the Person) attribute

- person1:
    age: 10
    name: 1
- person2:
    age: 20
    name: 2
- person3:
    age: 30
    name: 3
- person4:
    age: 40
    name: 4

@feelMySelfIsLouB
Copy link
Author

I try to match the property name in the ReadYaml method against Parser.Current, but it is difficult to determine the hierarchy if my Person object contains a List type property.

private class Person
{
    public string Id { get; set; }
    public int Age { get; set; }
    public string Name { get; set; }

    public List<Person> Child { get; set; }
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants