Add helper getters for URIs and date/times to json_rpc_2.
R=rnystrom@google.com
BUG=17700
Review URL: https://codereview.chromium.org//205713007
git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/json_rpc_2@34341 260f80e4-7a28-3924-810f-c04153c831b5
diff --git a/lib/src/parameters.dart b/lib/src/parameters.dart
index afc4a40..1e25220 100644
--- a/lib/src/parameters.dart
+++ b/lib/src/parameters.dart
@@ -224,7 +224,7 @@
/// Asserts that [value] exists and is a [Map] and returns it.
///
- /// [asListOr] may be used to provide a default value instead of rejecting the
+ /// [asMapOr] may be used to provide a default value instead of rejecting the
/// request if [value] doesn't exist.
Map get asMap => _getTyped('an Object', (value) => value is Map);
@@ -233,6 +233,32 @@
/// If [value] doesn't exist, this returns [defaultValue].
Map asMapOr(Map defaultValue) => asMap;
+ /// Asserts that [value] exists, is a string, and can be parsed as a
+ /// [DateTime] and returns it.
+ ///
+ /// [asDateTimeOr] may be used to provide a default value instead of rejecting
+ /// the request if [value] doesn't exist.
+ DateTime get asDateTime => _getParsed('date/time', DateTime.parse);
+
+ /// Asserts that [value] exists, is a string, and can be parsed as a
+ /// [DateTime] and returns it.
+ ///
+ /// If [value] doesn't exist, this returns [defaultValue].
+ DateTime asDateTimeOr(DateTime defaultValue) => asDateTime;
+
+ /// Asserts that [value] exists, is a string, and can be parsed as a
+ /// [Uri] and returns it.
+ ///
+ /// [asUriOr] may be used to provide a default value instead of rejecting the
+ /// request if [value] doesn't exist.
+ Uri get asUri => _getParsed('URI', Uri.parse);
+
+ /// Asserts that [value] exists, is a string, and can be parsed as a
+ /// [Uri] and returns it.
+ ///
+ /// If [value] doesn't exist, this returns [defaultValue].
+ Uri asUriOr(Uri defaultValue) => asUri;
+
/// Get a parameter named [named] that matches [test], or the value of calling
/// [orElse].
///
@@ -244,6 +270,27 @@
'"$method" must be $type, but was ${JSON.encode(value)}.');
}
+ _getParsed(String description, parse(String value)) {
+ var string = asString;
+ try {
+ return parse(string);
+ } on FormatException catch (error) {
+ // DateTime.parse doesn't actually include any useful information in the
+ // FormatException, just the string that was being parsed. There's no use
+ // in including that in the RPC exception. See issue 17753.
+ var message = error.message;
+ if (message == string) {
+ message = '';
+ } else {
+ message = '\n$message';
+ }
+
+ throw new RpcException.invalidParams('Parameter $_path for method '
+ '"$method" must be a valid $description, but was '
+ '${JSON.encode(string)}.$message');
+ }
+ }
+
void _assertPositional() {
// Throw the standard exception for a mis-typed list.
asList;
@@ -280,4 +327,8 @@
List asListOr(List defaultValue) => defaultValue;
Map asMapOr(Map defaultValue) => defaultValue;
+
+ DateTime asDateTimeOr(DateTime defaultValue) => defaultValue;
+
+ Uri asUriOr(Uri defaultValue) => defaultValue;
}
diff --git a/pubspec.yaml b/pubspec.yaml
index 0919ac1..f12be64 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -1,5 +1,5 @@
name: json_rpc_2
-version: 0.0.1
+version: 0.0.2
author: Dart Team <misc@dartlang.org>
description: An implementation of the JSON-RPC 2.0 spec.
homepage: http://www.dartlang.org
diff --git a/test/server/parameters_test.dart b/test/server/parameters_test.dart
index 9219475..8bd126a 100644
--- a/test/server/parameters_test.dart
+++ b/test/server/parameters_test.dart
@@ -20,6 +20,9 @@
"bool": true,
"string": "zap",
"list": [1, 2, 3],
+ "date-time": "1990-01-01 00:00:00.000",
+ "uri": "http://dartlang.org",
+ "invalid-uri": "http://[::1",
"map": {
"num": 4.2,
"bool": false
@@ -34,6 +37,9 @@
"bool": true,
"string": "zap",
"list": [1, 2, 3],
+ "date-time": "1990-01-01 00:00:00.000",
+ "uri": "http://dartlang.org",
+ "invalid-uri": "http://[::1",
"map": {
"num": 4.2,
"bool": false
@@ -195,6 +201,71 @@
expect(parameters['fblthp'].asMapOr({}), equals({}));
});
+ test("[].asDateTime returns date/time parameters", () {
+ expect(parameters['date-time'].asDateTime, equals(new DateTime(1990)));
+ });
+
+ test("[].asDateTimeOr returns date/time parameters", () {
+ expect(parameters['date-time'].asDateTimeOr(new DateTime(2014)),
+ equals(new DateTime(1990)));
+ });
+
+ test("[].asDateTime fails for non-date/time parameters", () {
+ expect(() => parameters['int'].asDateTime,
+ throwsInvalidParams('Parameter "int" for method "foo" must be a '
+ 'string, but was 1.'));
+ });
+
+ test("[].asDateTimeOr succeeds for absent parameters", () {
+ expect(parameters['fblthp'].asDateTimeOr(new DateTime(2014)),
+ equals(new DateTime(2014)));
+ });
+
+ test("[].asDateTime fails for non-date/time parameters", () {
+ expect(() => parameters['int'].asDateTime,
+ throwsInvalidParams('Parameter "int" for method "foo" must be a '
+ 'string, but was 1.'));
+ });
+
+ test("[].asDateTime fails for invalid date/times", () {
+ expect(() => parameters['string'].asDateTime,
+ throwsInvalidParams('Parameter "string" for method "foo" must be a '
+ 'valid date/time, but was "zap".'));
+ });
+
+ test("[].asUri returns URI parameters", () {
+ expect(parameters['uri'].asUri, equals(Uri.parse('http://dartlang.org')));
+ });
+
+ test("[].asUriOr returns URI parameters", () {
+ expect(parameters['uri'].asUriOr(Uri.parse('http://google.com')),
+ equals(Uri.parse('http://dartlang.org')));
+ });
+
+ test("[].asUri fails for non-URI parameters", () {
+ expect(() => parameters['int'].asUri,
+ throwsInvalidParams('Parameter "int" for method "foo" must be a '
+ 'string, but was 1.'));
+ });
+
+ test("[].asUriOr succeeds for absent parameters", () {
+ expect(parameters['fblthp'].asUriOr(Uri.parse('http://google.com')),
+ equals(Uri.parse('http://google.com')));
+ });
+
+ test("[].asUri fails for non-URI parameters", () {
+ expect(() => parameters['int'].asUri,
+ throwsInvalidParams('Parameter "int" for method "foo" must be a '
+ 'string, but was 1.'));
+ });
+
+ test("[].asUri fails for invalid URIs", () {
+ expect(() => parameters['invalid-uri'].asUri,
+ throwsInvalidParams('Parameter "invalid-uri" for method "foo" must '
+ 'be a valid URI, but was "http://[::1".\n'
+ 'Bad end of IPv6 host'));
+ });
+
group("with a nested parameter map", () {
var nested;
setUp(() => nested = parameters['map']);