Closed Brains closed 5 years ago
Is correct deserialization without attributes possible to achieve with Legivel.Mapper
customizations?
Interesting feature, never thought of this pattern.
The issue with Yaml to Discriminated Unions mapping is that you can identify various useful yaml-notation patterns, for which you need to process various nesting levels of Yaml Nodes. And support those, without excuding other features. Challenge :)
This pattern adds a new idea to what I had in mind (thanks!). The cost/Salary construct is the most interesting.
cost: Hourly 65
cost: Hourly (65)
Both are entries of a yaml mapping, key/value pairs. In both cases, a(ny) mapper would need to process the string, wich is contained in value part. That is not supported in the current version.
cost: {Hourly,65}
This could be changed to:
cost: {Hourly:65} # key/value pair
Which I expect it should be parseable with the current version.
The customizations in Legivel.Mapper
are meant for you to add your own mapping methods, while reuse what's already there. I haven't tested the usibility much for external parties. I'm doing offline an raml parser, using Legivel, and discovered that some stuff lacked customization. So if you'd like to use the customization, please regard that this area still "hot" for change.
The Yaml attributes are currently required to hint the parser what to do where, and keeping doors open for other features. If you'd like to do it without these attributes, this would resort to writing your own mapper, or customize the current one, wich is quite some work. Another way to keep you FSI script clean is to create an intermediate type, to which the mapper deserializes, and to map this intermediate to a clean target type.
Thanks for your contribution.
Which I expect it should be parseable with the current version.
Unfortunately, no. Or I'm just doing something wrong.
Here is slightly modified sample from your tutorial:
type UnionCase =
| One of int
| [<YamlValue("two")>] Two of int
Deserialize<UnionCase> "{One:1}"
Deserialize<UnionCase> "{two:2}"
and result:
> Deserialize<UnionCase> "{One:1}";;
val it : DeserializeResult<UnionCase> list =
[Error {Warn = [];
Error = [{Location = (l0, c0);
Message = "Document cannot be mapped";}];
StopLocation = (l1, c8);}]
> Deserialize<UnionCase> "{two:2}";;
val it : DeserializeResult<UnionCase> list =
[Error {Warn = [];
Error = [{Location = (l0, c0);
Message = "Document cannot be mapped";}];
StopLocation = (l1, c8);}]
Another way to keep you FSI script clean is to create an intermediate type, to which the mapper deserializes, and to map this intermediate to a clean target type.
Agree, also thought about that. Also, intermediate types will contain
type Value = {value:int}
so I can parse them like in your examples. Intermediate types resolve all problems at once.
Thank you for your repo.
Confirmed. This works:
type Value = {value:int}
[<YamlField("sal")>]
type Salary =
| Hourly of Value
Deserialize<Salary> "{value: 1, sal: Hourly}"
results in
> Deserialize<Salary> "{value: 1, sal: Hourly}";;
val it : DeserializeResult<Salary> list = [Succes {Data = Hourly {value = 1;};
Warn = [];}]
I have the type
type Entity = {
id : int
}
and yaml:
entities_014:
id: 14
which I parse succesfully with Legivel.
Is it now possible to switch to these types
type EntityId = EntityId of int
type Entity = {
id : EntityId
}
and still parse the same YAML files? From my understanding it was not possible at the time this issue was discussed, but has it changed in the last year?
Unfortunately, I haven't worked on this part. I'm still working very hard on improving Legivel's performance. Which appears to be a much bigger adventure than I anticipated.
Description
Need to deserialize
Discriminated Union
with primitiveint
data. Don't want to use attributesYamlValue, YamlField
to keep types clear for easy usage fromF# Interactive
Repro steps
type User = { name: string dept: string cost: Salary }
Expected behavior
Deserialize all data successfully
Actual behavior
Errors:
Known workarounds
Even with attributes
YamlValue, YamlField
can't manage it to work: