Git Product home page Git Product logo

Comments (7)

DanTup avatar DanTup commented on May 5, 2024

I tried adding my own formatter like this:

class JsonDateTimeRule extends CustomRule {
  bool appliesTo(instance, _) => instance is DateTime;
  List getState(DateTime date) => [_jsonDateFormatter.format(date)];
  DateTime create(List state) => _jsonDateFormatter.parse(state[0]);
  void setState(date, state) {}
}

However it seems to be ignored; and the type sig for CustomRule also only let me use List, so I'm not sure it would've doe what I wanted either.

from serialization.dart.

alan-knight avatar alan-knight commented on May 5, 2024

Yeah, that type sig is actually a lie. The generated classes override it
returning a Map. That really ought to be fixed. Made a separate bug.

When writing objects, the rules are processed in order until one of them
answers true to appliesTo(), so if you add yours after the default one it
will see the default one first and stop. To override the default rules, use
the Serialization.blank() constructor instead of the default. Or if you
want mostly the standard rules for base types, but just to replace one of
them,

var s = new Serialization.blank();
s.addRule(new JsonDateTimeRule());
s.addDefaultRules();

Now JsonDateTimeRule is first in the list and the other one will be ignored.

On Fri, Oct 31, 2014 at 12:04 PM, Danny Tuppeny [email protected]
wrote:

I tried adding my own formatter like this:

class JsonDateTimeRule extends CustomRule {
bool appliesTo(instance, _) => instance is DateTime;
List getState(DateTime date) => [_jsonDateFormatter.format(date)];
DateTime create(List state) => _jsonDateFormatter.parse(state[0]);
void setState(date, state) {}
}

However it seems to be ignored; and the type sig for CustomRule also only
let me use List, so I'm not sure it would've doe what I wanted either.


Reply to this email directly or view it on GitHub
#3 (comment)
.

from serialization.dart.

DanTup avatar DanTup commented on May 5, 2024

If I try to make my rule use a String, I get this error:

Illegal argument(s): Invalid argument, expected Map or Iterable, got 2014-11-01T16:46:20
#0      keysAndValues (package:serialization/src/serialization_helpers.dart:50:3)
#1      SerializationRule.flatten (package:serialization/src/serialization_rule.dart:77:18)
#2      Writer._flatten (package:serialization/src/reader_writer.dart:94:40)
#3      Writer.write (package:serialization/src/reader_writer.dart:77:13)
#4      Serialization.write (package:serialization/serialization.dart:334:35)
#5      main (file:///M:/Coding/DMS/DartDMS/test/test_serialisation.dart:23:23)
#6      _startIsolate (dart:isolate-patch/isolate_patch.dart:239)
#7      _startMainIsolate.<anonymous closure> (dart:isolate-patch/isolate_patch.dart:192)
#8      _RawReceivePortImpl._handleMessage (dart:isolate-patch/isolate_patch.dart:130)

Is there any way to have a custom rule that serialises as a string?

from serialization.dart.

alan-knight avatar alan-knight commented on May 5, 2024

Ah, right. It expects the result to be either a List or a Map, it doesn't
have a way to have a compound object that serializes into a primitive.

Off the top of my head there are a few ways you could work around that, but
none of them particularly lovely. So, as you would in Javascript, you're
going to need to somehow or other have code in objects that contain a date
that knows what to do with that field value.

  • You could manually write the rule for the containing object, but
    that's not great.
  • You could override the generated rule. So
    class Foo {int a, b; String c; DateTime d; }
    class MyRuleForFoo extends GeneratedRuleForFoo {
    getState(foo) { var basic = super.getState(foo); basic["d"]
    = myJsonVersion(foo.d)}
    setState(foo, state) { state["d"] =
    readADateFromMyJsonStringRepresentation(state["d]"); super.setState(foo,
    state); }
    That's not bad, but I'm not quite sure what the deserializer will do
    if it sees a DateTime in the input. It might just work, or you might need
    to give it another rule to make it treat that as a primitive.
  • If your consumer is reasonably lenient, and won't mind you also
    providing the default representation, you could provide a getter/setter
    pair for the version you want.
    class Foo { DateTime d; get dJson => myJsonVersion(d); set
    dJson(string) => readFromMyJsonString(string) }
    But the default generated rule will try to get/set both d and dJson.
    And if you're consuming JSON where only one is provided, then the order
    matters, so you might need to check for null and have a getter/setter for d
    as well. This wouldn't be necessary if you could tell the rule what to
    serialize, but the transformer doesn't have a way to do that, and if you
    don't use it you're back to writing your own rule. So you're stuck between
    very little control but easy, and complete control but hand-written. Or, if
    you can make d final, you could put dJson as a constructor parameter in the
    default constructor.

So probably overriding the generated rule is the nicest option, but I
haven't tried it.

On Sat Nov 01 2014 at 9:49:54 AM Danny Tuppeny [email protected]
wrote:

If I try to make my rule use a String, I get this error:

Illegal argument(s): Invalid argument, expected Map or Iterable, got 2014-11-01T16:46:20
#0 keysAndValues (package:serialization/src/serialization_helpers.dart:50:3)
#1 SerializationRule.flatten (package:serialization/src/serialization_rule.dart:77:18)
#2 Writer._flatten (package:serialization/src/reader_writer.dart:94:40)
#3 Writer.write (package:serialization/src/reader_writer.dart:77:13)
#4 Serialization.write (package:serialization/serialization.dart:334:35)
#5 main (file:///M:/Coding/DMS/DartDMS/test/test_serialisation.dart:23:23)
#6 _startIsolate (dart:isolate-patch/isolate_patch.dart:239)
#7 _startMainIsolate. (dart:isolate-patch/isolate_patch.dart:192)
#8 _RawReceivePortImpl._handleMessage (dart:isolate-patch/isolate_patch.dart:130)

Is there any way to have a custom rule that serialises as a string?


Reply to this email directly or view it on GitHub
#3 (comment)
.

from serialization.dart.

alan-knight avatar alan-knight commented on May 5, 2024

I shouldn't answer things off the top of my head. Disregard most of the previous.

A CustomRule is a simplified API that expects to read and write compound objects, and doesn't have the ability to encode as primitives. But that just means you need to write a more general SerializationRule if you need to do that. So, for example, the following serializes DateTime as its toString(). So its output would be like {a: something, b: 2014-11-03 10:16:17.475}

Note that if you did this the simple way, it would be write-only. There's no information in the format that tells me that the string should be parsed as a Date. That has to be encoded in the rule for the surrounding object. So for reading you're back to overriding the setState method in the rule for Thing, which we do here in OverriddenThingSerializationRule. I wrote the superclass by hand, so I could just put the code there, but I'm trying to illustrate doing it when the parent rule is generated.

Also, if you want to serialize a DateTime differently depending on the context, you would have to do both read and write code in the rule for the containing object.

See https://codereview.chromium.org/698983002

library serialize_date_as_string;

import "package:serialization/serialization.dart";

class DateAsStringSerializationRule extends SerializationRule {
bool appliesTo(x, _) => x is DateTime;
inflateEssential(state, reader) => DateTime.parse(state);
inflateNonEssential(state, object, reader) {}
extractState(obj, f, writer) => obj.toString();
flatten(object, Writer writer) {}
bool get storesStateAsPrimitives => true;
}

class ThingSerializationRule extends CustomRule {
appliesTo(x, _) => x is Thing;
getState(x) => { "a" : x.a, "b" : x.b};
create(state) => new Thing();
setState(thing, state) {
thing.a = state["a"];
thing.b = state["b"];
}
}

class OverriddenThingSerializationRule extends ThingSerializationRule {
setState(thing, state) {
var newState = new Map()..addAll(state);
newState["b"] = DateTime.parse(state["b"]);
super.setState(thing, newState);
}
}

class Thing {
String a;
DateTime b = new DateTime.now();
toString() => "Thing: a = $a, b = $b";
}

main() {
var t = new Thing()..a="something";
var s = new Serialization.blank(format: new SimpleJsonFormat(storeRoundTripInfo: true))
..addRule(new OverriddenThingSerializationRule())
..addRule(new DateAsStringSerializationRule())
..addDefaultRules();
var written = s.write(t);
print(written);
var readBack = s.read(written);
print(readBack);
}

from serialization.dart.

DanTup avatar DanTup commented on May 5, 2024

Given this is going to be such a common scenario; wouldn't it make sense to build this in? With mirrors or generated rules; you know when a string is a DateTime; so you could just pick a standard format to use by default, and allow it to be overriden?

from serialization.dart.

alan-knight avatar alan-knight commented on May 5, 2024

It might. I'd rather see multiple instances of the requirement, and if it
might apply to other things, before trying to graduate it from a pattern
with an example to a built-in.

On Mon, Nov 3, 2014 at 12:57 PM, Danny Tuppeny [email protected]
wrote:

Given this is going to be such a common scenario; wouldn't it make sense
to build this in? With mirrors or generated rules; you know when a string
is a DateTime; so you could just pick a standard format to use by default,
and allow it to be overriden?


Reply to this email directly or view it on GitHub
#3 (comment)
.

from serialization.dart.

Related Issues (11)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo 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.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.