@@ -1,8 +1,6 @@
Loading
1 -
import 'dart:convert';
2 -
3 -
import 'package:json_string/src/errors.dart';
4 1
import 'package:json_string/src/functions.dart';
5 2
import 'package:json_string/src/utils.dart';
3 +
import 'package:json_util/json_util.dart';
6 4
7 5
/// A single piece of JSON data.
8 6
class JsonString {
@@ -19,30 +17,19 @@
Loading
19 17
  /// a cache of the decoded value is provided.
20 18
  factory JsonString(String source, {bool enableCache = false}) {
21 19
    assert(source != null);
22 -
    try {
23 -
      final decodedSource = _decodeSafely(source);
24 -
      final cachedValue = enableCache ? decodedSource : null;
25 -
      return JsonString._(_encode(decodedSource), cachedValue);
26 -
    } on FormatException catch (e) {
27 -
      throw JsonFormatException.fromParent(e);
28 -
    } catch (_) {
29 -
      throw JsonFormatException(
30 -
          "This source does not represent a valid JSON.", source);
31 -
    }
20 +
    return _constructJsonString(source, enableCache);
32 21
  }
33 22
34 23
  /// Constructs a [JsonString] if [source] is a valid JSON.
35 24
  ///
36 -
  /// If not, it returns [null].
25 +
  /// If not, it returns `null`.
37 26
  ///
38 27
  /// If the optional [enableCache] parameter is set to `true`,
39 28
  /// a cache of the decoded value is provided.
40 29
  factory JsonString.orNull(String source, {bool enableCache = false}) {
41 30
    assert(source != null);
42 31
    try {
43 -
      final decodedSource = _decodeSafely(source);
44 -
      final cachedValue = enableCache ? decodedSource : null;
45 -
      return JsonString._(_encode(decodedSource), cachedValue);
32 +
      return _constructJsonString(source, enableCache);
46 33
    } catch (_) {
47 34
      return null;
48 35
    }
@@ -55,27 +42,31 @@
Loading
55 42
  /// Attention: this is just a wrapper around the Dart built-in
56 43
  /// function `json.encode()`, you should use this in special cases only.
57 44
  /// Check the other encoding functions for more common usages.
58 -
  JsonString.encode(Object value, {encoder(object)})
59 -
      : this.source = _encodeSafely(value, encoder: encoder),
60 -
        this._cachedValue = null;
45 +
  JsonString.encode(Object value, {Function(Object object) encoder})
46 +
      : source = _encodeSafely(value, encoder: encoder),
47 +
        _cachedValue = null;
61 48
62 49
  /// Constructs a [JsonString] converting [value] into a valid JSON
63 50
  /// primitive value.
64 51
  ///
65 -
  /// [T] must be a primitive type (int, double, bool or String).
52 +
  /// [T] must be a primitive type (int, double, bool, String or Null).
66 53
  static JsonString encodePrimitiveValue<T>(T value) {
67 54
    assert(value != null);
68 -
    final primitiveValue = checkPrimitiveValue(value);
69 -
    return JsonString.encode(primitiveValue);
55 +
    return wrapJsonUtilOperation(() {
56 +
      final encodable = EncodableValue.fromPrimitiveValue<T>(value);
57 +
      return JsonString._(encodable.encode(), null);
58 +
    });
70 59
  }
71 60
72 61
  /// Constructs a [JsonString] converting [list] into a valid JSON List.
73 62
  ///
74 -
  /// [T] must be a primitive type (int, double, bool or String).
63 +
  /// [T] must be a primitive type (int, double, bool, String or Null).
75 64
  static JsonString encodePrimitiveList<T>(List<T> list) {
76 65
    assert(list != null);
77 -
    final dynamicList = disassemblePrimitiveList<T>(list);
78 -
    return JsonString.encode(dynamicList);
66 +
    return wrapJsonUtilOperation(() {
67 +
      final encodable = EncodableValue.fromPrimitiveList<T>(list);
68 +
      return JsonString._(encodable.encode(), null);
69 +
    });
79 70
  }
80 71
81 72
  /// Constructs a [JsonString] converting [value] into a
@@ -87,8 +78,11 @@
Loading
87 78
  static JsonString encodeObject<T extends Object>(T value,
88 79
      {JsonObjectEncoder<T> encoder}) {
89 80
    assert(value != null);
90 -
    final dynamicMap = disassembleObject<T>(value, builder: encoder);
91 -
    return JsonString.encode(dynamicMap);
81 +
    return wrapJsonUtilOperation(() {
82 +
      final dynamicMap = disassembleObject<T>(value, builder: encoder);
83 +
      final encodable = EncodableValue.map(dynamicMap);
84 +
      return JsonString._(encodable.encode(), null);
85 +
    });
92 86
  }
93 87
94 88
  /// Constructs a [JsonString] converting [list] into a valid JSON list.
@@ -97,8 +91,11 @@
Loading
97 91
  static JsonString encodeObjectList<T extends Object>(List<T> list,
98 92
      {JsonObjectEncoder<T> encoder}) {
99 93
    assert(list != null);
100 -
    final dynamicList = disassembleObjectList<T>(list, builder: encoder);
101 -
    return JsonString.encode(dynamicList);
94 +
    return wrapJsonUtilOperation(() {
95 +
      final dynamicList = disassembleObjectList<T>(list, builder: encoder);
96 +
      final encodable = EncodableValue.list(dynamicList);
97 +
      return JsonString._(encodable.encode(), null);
98 +
    });
102 99
  }
103 100
104 101
  // <<decoding properties>>
@@ -107,19 +104,21 @@
Loading
107 104
  ///
108 105
  /// (this is the most general one.)
109 106
  dynamic get decodedValue =>
110 -
      (_cachedValue != null) ? _cachedValue : _decodeSafely(this.source);
107 +
      wrapJsonUtilOperation<dynamic>(() => _decodedValue.value);
111 108
112 109
  /// The JSON data decoded as an instance of [Map<String, dynamic>].
113 110
  ///
114 111
  /// The JSON data must be a JSON object or it will throw
115 112
  /// a [JsonDecodingError].
116 -
  Map<String, dynamic> get decodedValueAsMap => castToMap(this.decodedValue);
113 +
  Map<String, dynamic> get decodedValueAsMap =>
114 +
      wrapJsonUtilOperation(() => _decodedValue.asMap());
117 115
118 116
  /// The JSON data decoded as an instance of [List<dynamic>].
119 117
  ///
120 118
  /// The JSON data must be a JSON list or it will throw
121 119
  /// a [JsonDecodingError].
122 -
  List<dynamic> get decodedValueAsList => castToList(this.decodedValue);
120 +
  List<dynamic> get decodedValueAsList =>
121 +
      wrapJsonUtilOperation(() => _decodedValue.asList());
123 122
124 123
  // <<decoding methods>>
125 124
@@ -128,7 +127,7 @@
Loading
128 127
  /// The JSON data must be a JSON primitive value and [T] must be a primitive
129 128
  ///  type (int, double, bool or String) or it will throw a [JsonDecodingError].
130 129
  T decodeAsPrimitiveValue<T>() =>
131 -
      castToPrimitiveTypedValue<T>(this.decodedValue);
130 +
      wrapJsonUtilOperation(() => _decodedValue.asPrimitiveValue<T>());
132 131
133 132
  /// Returns the JSON data decoded as an instance of [List<T>].
134 133
  ///
@@ -136,21 +135,27 @@
Loading
136 135
  /// be a primitive type (int, double, bool or String) or it will throw
137 136
  /// a [JsonDecodingError].
138 137
  List<T> decodeAsPrimitiveList<T>() =>
139 -
      castToPrimitiveList<T>(this.decodedValue);
138 +
      wrapJsonUtilOperation(() => _decodedValue.asPrimitiveList<T>());
140 139
141 140
  /// Returns the JSON data decoded as an instance of [T extends Object].
142 141
  ///
143 142
  /// The JSON data must be a JSON object or it will throw
144 143
  /// a [JsonDecodingError].
145 -
  T decodeAsObject<T extends Object>(JsonObjectDecoder<T> decoder) =>
146 -
      assembleObject<T>(this.decodedValueAsMap, decoder);
144 +
  T decodeAsObject<T extends Object>(JsonObjectDecoder<T> decoder) {
145 +
    assert(decoder != null);
146 +
    return wrapJsonUtilOperation(
147 +
        () => _decodedValue.asObject(decoder, skipIfNull: true));
148 +
  }
147 149
148 150
  /// Returns the JSON data decoded as an instance of [List<T extends Object>].
149 151
  ///
150 152
  /// The JSON data must be a list of JSON objects or it
151 153
  /// will throw a [JsonDecodingError].
152 -
  List<T> decodeAsObjectList<T extends Object>(JsonObjectDecoder<T> decoder) =>
153 -
      assembleObjectList<T>(this.decodedValueAsList, decoder);
154 +
  List<T> decodeAsObjectList<T extends Object>(JsonObjectDecoder<T> decoder) {
155 +
    assert(decoder != null);
156 +
    return wrapJsonUtilOperation(
157 +
        () => _decodedValue.asObjectList(decoder, skipNullValues: true));
158 +
  }
154 159
155 160
  // <<standard methods>>
156 161
@@ -169,33 +174,32 @@
Loading
169 174
    return 'JsonString{source: $source}';
170 175
  }
171 176
177 +
  // <<private constructor>>
178 +
179 +
  const JsonString._(this.source, this._cachedValue);
180 +
172 181
  // <<private fields>>
173 182
174 -
  final dynamic _cachedValue;
183 +
  final DecodedValue _cachedValue;
175 184
176 -
  // <<private methods>>
185 +
  // <<private getters>>
177 186
178 -
  const JsonString._(this.source, this._cachedValue);
187 +
  DecodedValue get _decodedValue =>
188 +
      (_cachedValue != null) ? _cachedValue : DecodedValue.from(source);
189 +
190 +
  // <<private static methods>>
179 191
180 -
  static String _encode(Object value, {Function(Object) encoder}) {
181 -
    return json.encode(value, toEncodable: encoder);
192 +
  static JsonString _constructJsonString(String source, bool enableCache) {
193 +
    final decodedSource = DecodedValue.from(source);
194 +
    final cachedValue = enableCache ? decodedSource : null;
195 +
    return JsonString._(convertEncode(decodedSource.value), cachedValue);
182 196
  }
183 197
184 198
  static String _encodeSafely(Object value, {Function(Object) encoder}) {
185 -
    assert(value != null);
186 199
    try {
187 -
      return json.encode(value, toEncodable: encoder);
200 +
      return convertEncode(value, toEncodable: encoder);
188 201
    } catch (e) {
189 202
      throw JsonEncodingError(e);
190 203
    }
191 204
  }
192 -
193 -
  static Object _decodeSafely(String source,
194 -
      {Function(Object key, Object value) decoder}) {
195 -
    try {
196 -
      return json.decode(source, reviver: decoder);
197 -
    } catch (e) {
198 -
      throw JsonDecodingError(e);
199 -
    }
200 -
  }
201 205
}

@@ -9,6 +9,6 @@
Loading
9 9
/// An object that can be encoded into some valid JSON.
10 10
mixin Jsonable implements _Jsonable {
11 11
  Map<String, dynamic> toMap() {
12 -
    return this.toJson();
12 +
    return toJson();
13 13
  }
14 14
}

@@ -1,154 +1,40 @@
Loading
1 -
import 'package:json_string/src/errors.dart';
2 1
import 'package:json_string/src/functions.dart';
3 2
import 'package:json_string/src/jsonable.dart';
3 +
import 'package:json_util/json_util.dart';
4 4
5 -
T checkPrimitiveValue<T>(T value) {
6 -
  assert(value != null);
7 -
  if (!isPrimitiveType<T>()) {
8 -
    throw JsonEncodingError(
9 -
        "type '${T.toString()}' is not a JSON primitive type");
10 -
  }
11 -
  return value;
12 -
}
13 -
5 +
/// Makes an object ready to be encoded.
14 6
Map<String, dynamic> disassembleObject<T extends Object>(T value,
15 7
    {JsonObjectEncoder<T> builder}) {
16 -
  assert(value != null);
17 -
  final T dartObject = value;
8 +
  final dartObject = value;
18 9
  if (builder != null) {
19 10
    return builder(dartObject);
20 11
  } else if (dartObject is Jsonable) {
21 12
    return dartObject.toMap();
22 13
  }
23 14
  throw JsonEncodingError(
24 -
      "this is not a Jsonable object: provide a valid encoder.");
25 -
}
26 -
27 -
List<dynamic> disassemblePrimitiveList<T>(List<T> value) {
28 -
  assert(value != null);
29 -
  final List<T> primitiveList = value;
30 -
  if (!isPrimitiveType<T>()) {
31 -
    throw JsonEncodingError(
32 -
        "type '${T.toString()}' is not a JSON primitive type");
33 -
  }
34 -
  return primitiveList;
15 +
      'this is not a Jsonable object: provide a valid encoder.');
35 16
}
36 17
37 -
List<dynamic> disassembleObjectList<T extends Object>(List<T> value,
18 +
/// Makes a list of objects ready to be encoded.
19 +
List<Map<String, dynamic>> disassembleObjectList<T extends Object>(
20 +
    List<T> value,
38 21
    {JsonObjectEncoder<T> builder}) {
39 -
  assert(value != null);
40 -
  final List<T> dartObjectList = value;
22 +
  final dartObjectList = value;
41 23
  return dartObjectList.map((e) {
42 24
    if (e == null) {
43 -
      return normalizeJsonObject(e);
25 +
      return e as Map<String, dynamic>;
44 26
    }
45 27
    return disassembleObject<T>(e, builder: builder);
46 28
  }).toList();
47 29
}
48 30
49 -
T assembleObject<T extends Object>(
50 -
    Map<String, dynamic> jsonObject, JsonObjectDecoder<T> builder) {
51 -
  assert(jsonObject != null);
52 -
  assert(builder != null);
53 -
  return builder(jsonObject);
54 -
}
55 -
56 -
List<T> assembleObjectList<T extends Object>(
57 -
    List<dynamic> jsonList, JsonObjectDecoder<T> builder) {
58 -
  assert(jsonList != null);
59 -
  assert(builder != null);
60 -
  return jsonList.map((e) {
61 -
    if (e == null) {
62 -
      return e as T;
63 -
    }
64 -
    final map = castToMap(e);
65 -
    return assembleObject<T>(map, builder);
66 -
  }).toList();
67 -
}
68 -
69 -
Map<String, dynamic> castToMap(dynamic value) {
70 -
  assert(value != null);
71 -
  final Object jsonObject = value;
72 -
  if (!isMap(jsonObject)) {
73 -
    throw JsonDecodingError(
74 -
        "value '${jsonObject.toString()}' is not an instance of Map<String, dynamic>");
75 -
  }
76 -
  return normalizeJsonObject(jsonObject);
77 -
}
78 -
79 -
List<dynamic> castToList(dynamic value) {
80 -
  assert(value != null);
81 -
  final Object jsonList = value;
82 -
  if (!isList(jsonList)) {
83 -
    throw JsonDecodingError(
84 -
        "value '${jsonList.toString()}' is not an instance of List<dynamic>");
85 -
  }
86 -
  return jsonList as List<dynamic>;
87 -
}
88 -
89 -
List<T> castToPrimitiveList<T>(dynamic value) {
90 -
  assert(value != null);
91 -
  if (!isPrimitiveType<T>()) {
92 -
    throw JsonDecodingError(
93 -
        "type '${T.toString()}' is not a JSON primitive type");
94 -
  }
95 -
  final Object jsonList = value;
96 -
  if (!isTypedList<T>(jsonList)) {
97 -
    throw JsonDecodingError(
98 -
        "value '${jsonList.toString()}' is not an instance of List<${T.toString()}>");
99 -
  }
100 -
  return List<T>.from(jsonList);
101 -
}
102 -
103 -
T castToPrimitiveTypedValue<T>(dynamic value) {
104 -
  if (!isPrimitiveType<T>()) {
105 -
    throw JsonDecodingError(
106 -
        "type '${T.toString()}' is not a JSON primitive type");
107 -
  }
108 -
  if (!isTypedValue<T>(value)) {
109 -
    throw JsonDecodingError(
110 -
        "value '${value.toString()}' is not an instance of ${T.toString()}");
31 +
/// Wrap a generic operation from json_util library
32 +
T wrapJsonUtilOperation<T>(T Function() exec) {
33 +
  try {
34 +
    return exec();
35 +
  } on DecodedValueError catch (e) {
36 +
    throw JsonDecodingError(e);
37 +
  } on EncodableValueError catch (e) {
38 +
    throw JsonEncodingError(e);
111 39
  }
112 -
  return value as T;
113 -
}
114 -
115 -
bool isPrimitiveType<T>() {
116 -
  Type type = T;
117 -
  final ts = type.toString();
118 -
  return ts == 'bool' || ts == 'String' || ts == 'int' || ts == 'double';
119 -
}
120 -
121 -
bool isMap(dynamic node) {
122 -
  return node is Map<String, dynamic>;
123 -
}
124 -
125 -
bool isList(dynamic node) {
126 -
  return node is List<dynamic>;
127 -
}
128 -
129 -
bool isTypedList<T>(dynamic node) {
130 -
  if (!isList(node)) {
131 -
    return false;
132 -
  }
133 -
  for (final e in node) {
134 -
    if (e == null) {
135 -
      continue;
136 -
    }
137 -
    if (!(e is T)) {
138 -
      return false;
139 -
    }
140 -
  }
141 -
  return true;
142 -
}
143 -
144 -
bool isTypedValue<T>(dynamic node) {
145 -
  final e = node;
146 -
  if (e == null) {
147 -
    return true;
148 -
  }
149 -
  return e is T;
150 -
}
151 -
152 -
Map<String, dynamic> normalizeJsonObject(Object jsonObject) {
153 -
  return jsonObject as Map<String, dynamic>;
154 40
}
Files Coverage
lib/src 100.00%
Project Totals (3 files) 100.00%
Untitled

No yaml found.

Create your codecov.yml to customize your Codecov experience

Sunburst
The inner-most circle is the entire project, moving away from the center are folders then, finally, a single file. The size and color of each slice is representing the number of statements and the coverage, respectively.
Icicle
The top section represents the entire project. Proceeding with folders and finally individual files. The size and color of each slice is representing the number of statements and the coverage, respectively.
Grid
Each block represents a single file in the project. The size and color of each block is represented by the number of statements and the coverage, respectively.
Loading