-
-
Notifications
You must be signed in to change notification settings - Fork 491
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
IYamlTypeConverter.readYAML is too limited? #168
Comments
It seems something similar holds for |
Hi, |
Yeah, making an API for hypothetical usecases is always tricky. As for a pullrequest - my project is on a bit of a tight schedule, so I will probably have to just work around the problem if possible. I might look at a proper solution, though. What's your take on backward compatibility? Changing |
A possible fix for this issue is in #203. This eliminates |
I could be missing something but I believe this is still an issue. I've spent a day or so trying to figure out how to properly support my custom type serialization/deserialization, including looking through the code a fair amount, and I can't find a way that's both symmetrical and properly nests. If I use IYamlTypeConverter, I can't find a way to dispatch to a nestedObjectSerializer/Deserializer, which means I seem to need to parse the whole object hierarchy in a single IYamlTypeConverter. What I really want is to define/register an IYamlTypeConverter for each custom type and but still be able to invoke the framework to handle nesting or built-in types. I notice that I CAN do this on the deserialization side if I use INodeDeserializer because Deserialize has a nestedObjectDeserializer but that doesn't cover the serialization side (and, maybe I'm being dense, but I can't find anything like an INodeSerializer interface). I also seem to be able to do it if each of my types implements IYamlConvertible but I strongly, strongly dislike coupling my types to any specific serialization framework (and this also requires me to make my types mutable, which I was hoping to avoid). I think this can be resolved by adding a nestedObjectDeserializer to IYamlTypeConverter.Read and a nestedObjectSerializer to IYamlTypeConverter.Write. If I'm missing something, please let me know. |
You are correct that this is a limitation of |
Hi! Thanks for all the effort you have put in your library. For the moment, I'm going to have to reluctantly implement IYamlConvertible on my classes, because that appears to be currently the only simple way to customize the serialization/deserialization processes. |
@antoinebj While it is true that the interface could be improved, it seems suitable to your use case. There's no need to implement any visitor. This is how I would do it: public class ApplyNamingConventionToEnums : IYamlTypeConverter
{
private readonly INamingConvention namingConvention;
public ApplyNamingConventionToEnums(INamingConvention namingConvention)
{
this.namingConvention = namingConvention;
}
public bool Accepts(Type type)
{
return type.IsEnum;
}
public object ReadYaml(IParser parser, Type type)
{
var scalar = parser.Expect<Scalar>();
// Naming conventions are not bidirectional, so we need to test each value.
// This is unfortunate but this implementation could be improved.
var names = Enum.GetNames(type);
var valueAsString = names.First(n => namingConvention.Apply(n).Equals(scalar.Value));
return Enum.Parse(type, valueAsString);
}
public void WriteYaml(IEmitter emitter, object value, Type type)
{
var valueAsString = namingConvention.Apply(value.ToString());
emitter.Emit(new Scalar(valueAsString));
}
} Check a working example that uses this code: https://dotnetfiddle.net/JyyiVV |
@aaubry This is great, thank you very much! |
Are there any chances that that |
This issue appears to be abandoned, I'm going to close it. |
I've been working on a custom deserializer, by implementing the
INodeDeserializer
interface. ItsDeserialize
method has access to theEventReader
object, allowing the use of e.g.reader.Expect()
and it has access to anestedObjectDeserializer
, which can be used to deserialize parts of my object using the default rules (I'm deserializing a custom vector class, which is written as a list of two integers).When adding custom serialization for the same class, I found that that needed a custom
IYamlTypeConverter
implementation. That interface seems to handle deserialization as well, so it seems it is easy to implement both serialization and deserialization in the same class. However, itsreadYaml()
method only gets passed theIParser
andType
objects, which (AFAICS) make it a lot more tricky to actually parse a more complicated object. Perhaps this interface was intended for converting simple scalar values, but it seems a missed opportunity that it does not get the same values asDeserialize()
so it is way more powerful.When I started writing this report, I believed that his would prevent me from properly deserializing (because the type converter does not have a way to only handle serialization, so it would prevent my custom
INodeDeserializer
from running), but I just realized that I can just not register the type converter when doing deserialization, which should allow me to use theINodeDeserializer
for deserialization and theIYamlTypeConverter
for serialization.Still, it would be nice to have a more symmetrical way to do this. Of course, I might be misunderstanding the purpose of these interfaces and there might be a better way - I'm mostly guessing around based on looking around the sources, of course :-)
The text was updated successfully, but these errors were encountered: