Reputation: 87
I am trying to deserialize some YAML that has !!set in a string created by SnakeYaml when serializing Java HashSet. Different generic types are serialized, for example HashSet and with custom type HashSet.
Example YAML:
holidays: !!set
? DDMMYYYY: 25/12/2042
MMDDYYYY: 12/25/2042
date:
chronology: &id001
calendarType: iso8601
id: ISO
dayOfMonth: 25
dayOfWeek: THURSDAY
dayOfYear: 359
era: CE
leapYear: false
month: DECEMBER
monthValue: 12
year: 2042
serialValue: 52225
: null
I initially get exception:
Additional information: Could not load file or assembly '2002:set' or one of its dependencies. The system cannot find the file specified.
To fix, I register tag mapping to Deserializer:
{"tag:yaml.org,2002:set", typeof (HashSet<object>)}
I then get exception:
A first chance exception of type 'YamlDotNet.Core.YamlException' occurred in YamlDotNet.dll Additional information: (Line: 4, Col: 23, Idx: 108) - (Line: 5, Col: 9, Idx: 122): Expected 'SequenceStart', got 'MappingStart' (at Line: 4, Col: 23, Idx: 108).
I would have thought handling sets is a very common requirement for YAML, but I can't figure out how to fix this.
Can anyone advise as to how to handle?
Upvotes: 1
Views: 1486
Reputation: 12469
The problem is that HashSet<T>
does not implement IDictionary<TKey, TValue>
, and is then deserialized as a sequence instead of a mapping.
You will need to create your own implementation of a set, perhaps by extending HashSet<T>
and implementing IDictionary<T, object>
like this:
public class YamlSet<T> : HashSet<T>, IDictionary<T, object>
{
void IDictionary<T, object>.Add(T key, object value)
{
Add(key);
}
object IDictionary<T, object>.this[T key]
{
get
{
throw new NotImplementedException();
}
set
{
Add(key);
}
}
// ...
}
There are more members of IDictionary<T, object>
that you will have to implement, but these are the ones that are necessary to make deserialization work.
See a fully working example here
Upvotes: 1