Comments (3)
Hi @Matej-Hlatky, I would be interested in your opinion on an XmlConverter
annotation vs fromXml...
and toXml...
fields on the existing annotations. I am not entirely sure that XmlConverter
would be able to work quite like JsonConverter
. The field being serialized could be an XmlAttribute
or an XmlElement
to name a few, and whilst the developer is likely only interested in the value of the XmlAttribute
, they might be interested in the entire XmlElement
instead of just its text, especially if the XmlElement
contains nested children. Here are some of the different proposals that I have considered so far:
@annotation.XmlSerializable()
class One {
@annotation.XmlAttribute(fromXmlAttribute: base64BinaryFromXmlAttribute, toXmlAttribute: base64BinaryToXmlAttribute)
Uint8List attribute;
@annotation.XmlElement(fromXmlElement: base64BinaryFromXmlElement, toXmlElement: base64BinaryToXmlElement)
Uint8List element;
...
}
Uint8List base64BinaryFromXmlAttribute(XmlAttribute attribute) {
return base64.decode(attribute.value);
}
XmlAttribute base64BinaryToXmlAttribute(Uint8List value) {
return XmlAttribute(XmlName('???'), base64.encode(value));
}
Uint8List base64BinaryFromXmlElement(XmlElement element) {
final text = element.getText()!;
return base64.decode(text);
}
XmlElement base64BinaryToXmlElement(Uint8List value) {
final text = base64.encode(value);
return XmlElement(XmlName('???'), [], [XmlText(text)]);
}
@annotation.XmlSerializable()
class Two {
@annotation.XmlAttribute(fromXml: base64BinaryFromXml, toXml: base64BinaryToXml)
Uint8List attribute;
@annotation.XmlElement(fromXml: base64BinaryFromXml, toXml: base64BinaryToXml)
Uint8List element;
...
}
Uint8List base64BinaryFromXml(String value) => base64.decode(value);
String base64BinaryToXml(Uint8List value) => base64.encode(value);
// xml_annotation/lib/src/annotations/xml_attribute_converter.dart
abstract class XmlAttributeConverter<T> {
const XmlAttributeConverter();
T fromXmlAttribute(XmlAttribute attribute);
XmlAttribute toXmlAttribute(T object);
}
// xml_annotation/lib/src/annotations/xml_element_converter.dart
abstract class XmlElementConverter<T> {
const XmlElementConverter();
T fromXmlElement(XmlElement element);
XmlElement toXmlElement(T object);
}
@annotation.XmlSerializable()
class Three {
@annotation.XmlAttribute()
@Base64BinaryConverter()
Uint8List attribute;
@annotation.XmlElement()
@Base64BinaryConverter()
Uint8List element;
...
}
class Base64BinaryConverter implements annotation.XmlAttributeConverter<Uint8List>, annotation.XmlElementConverter<Uint8List> {
const Base64BinaryConverter();
@override
Uint8List fromXmlAttribute(XmlAttribute attribute) {
return base64.decode(attribute.value);
}
@override
XmlAttribute toXmlAttribute(Uint8List object) {
return XmlAttribute(XmlName('???'), base64.encode(object));
}
@override
Uint8List fromXmlElement(XmlElement element) {
final text = element.getText()!;
return base64.decode(text);
}
@override
XmlElement toXmlElement(Uint8List object) {
final text = base64.encode(object);
return XmlElement(XmlName('???'), [], [XmlText(text)]);
}
}
// xml_annotation/lib/src/annotations/xml_converter.dart
abstract class XmlConverter<T> {
const XmlConverter();
T fromXml(String value);
String toXml(T object);
}
@annotation.XmlSerializable()
class Four {
@annotation.XmlAttribute()
@Base64BinaryConverter()
Uint8List attribute;
@annotation.XmlElement()
@Base64BinaryConverter()
Uint8List element;
...
}
class Base64BinaryConverter implements annotation.XmlConverter<Uint8List> {
const Base64BinaryConverter();
@override
Uint8List fromXml(String value) => base64.decode(value);
@override
String toXml(Uint8List object) => base64.encode(object);
}
Two
is simpler than One
but it doesn't support creating an instance of the custom type using nested children.
Four
is the equivalent of Two
using a custom XmlConverter
annotation instead of fromXml
and toXml
fields.
from dart-xml-serializable.
Hi @tnc1997 ,
personally, I couldn't find any real use case for XML element conversion, but only attribute (aka scalar type) --
String
to base64binary
, time
, ...
Of course, sometimes you need to map whole XML document (or JSON Object, GraphQL Fragment) to your specific model,
however this shoudl be dealt with in Domain layer.
Also usage of types of converted types instead of "raw" XML elements from XSD schema or other documentation could make it not only harder to write and validate, but then also harder to debug just by comparing the structure "optically" and also writing tests.
So let's stick to the attribute (scalar) mapping; same as in json_convert
for JSON and GraphQL does it.
from dart-xml-serializable.
I couldn't find any real use case for XML element conversion.
It looks like JsonConvert
allows conversion to/from Map<String, dynamic>
, which would allow converting a nested object (e.g. {"date": "2023-10-08", "time": "12:00:00"}
) to/from a type (e.g. DateTime
). In theory a Map<String, dynamic>
is somewhat synonymous with an XmlElement
. That being said, I do agree that opting for just scalar mapping is easier and simpler.
{
"a": { "year": 2023, "month": 10, "day": 8 },
"b": 1696793104943
}
@JsonSerializable()
class Example {
@_CustomDateTimeConverter()
final DateTime a;
@_EpochDateTimeConverter()
final DateTime b;
...
}
class _CustomDateTimeConverter implements JsonConverter<DateTime, Map<String, dynamic>> {
const _CustomDateTimeConverter();
@override
DateTime fromJson(Map<String, dynamic> json) => DateTime(json['year'] as int, json['month'] as int, json['day'] as int);
@override
Map<String, dynamic> toJson(DateTime object) => {'year': object.year, 'month': object.month, 'day': object.day};
}
class _EpochDateTimeConverter implements JsonConverter<DateTime, int> {
const _EpochDateTimeConverter();
@override
DateTime fromJson(int json) => DateTime.fromMillisecondsSinceEpoch(json);
@override
int toJson(DateTime object) => object.millisecondsSinceEpoch;
}
<?xml version="1.0" encoding="UTF-8"?>
<example b="1696793104943">
<a>
<year>2023</year>
<month>10</month>
<day>8</day>
</a>
</example>
@annotation.XmlSerializable()
class Example {
@annotation.XmlElement()
@_CustomDateTimeConverter()
final DateTime a;
@annotation.XmlAttribute()
@_EpochDateTimeConverter()
final DateTime b;
...
}
class _CustomDateTimeConverter implements annotation.XmlElementConverter<DateTime> {
const _CustomDateTimeConverter();
@override
DateTime fromXmlElement(XmlElement element) => DateTime(
int.parse(element.getElement('year')!.getText()!),
int.parse(element.getElement('month')!.getText()!),
int.parse(element.getElement('day')!.getText()!),
);
@override
XmlElement toXmlElement(DateTime object) => XmlElement(
XmlName('???'),
[],
[
XmlElement(XmlName('year'), [], [XmlText(object.year.toString())]),
XmlElement(XmlName('month'), [], [XmlText(object.month.toString())]),
XmlElement(XmlName('day'), [], [XmlText(object.day.toString())]),
],
);
}
class _EpochDateTimeConverter implements annotation.XmlAttributeConverter<DateTime> {
const _EpochDateTimeConverter();
@override
DateTime fromXmlAttribute(XmlAttribute attribute) => DateTime.fromMillisecondsSinceEpoch(int.parse(attribute.value));
@override
XmlAttribute toXmlAttribute(DateTime object) => XmlAttribute(XmlName('???'), object.millisecondsSinceEpoch.toString());
}
from dart-xml-serializable.
Related Issues (20)
- Deserialization of enum iterables is broken due to duplicate variables HOT 4
- Only deserialize fields with an annotation in generate from XML element HOT 5
- Enum-Serializtion does not work anymore if split between multiple files HOT 1
- Reduce boilerplate code HOT 1
- Include beginner friendly docs HOT 1
- ignore attributes HOT 2
- How to describe a self closing optional element? HOT 3
- Add support for fields in superclasses HOT 8
- Add support for import prefixes HOT 3
- Asynchronous deserialization with Streams HOT 3
- Some methods not generated by builder HOT 3
- Dynamically choose names for XML-elements HOT 3
- feat: Add support for XML base64Binary type HOT 3
- Add support for serializing XML CDATA HOT 2
- Upgrade the version constraint of analyzer HOT 1
- Add support for serializing elements using InnerXml HOT 7
- Better deserialization of empty elements / empty strings HOT 7
- Created List of single null class object but xml element is empty HOT 4
- Nullable fields annotated with XmlCDATA results in incorrectly generated source code HOT 1
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from dart-xml-serializable.