Decoding JSON in dart - dart

I have this simple dart file which I'm running:
import 'dart:convert';
// ...
dynamic test() {
final strJson = '{"ACB":["{\"date\":\"2020-02-28\",\"open\":1.36,\"close\":1.34,\"high\":1.4,\"low\":1.32,\"volume\":26469238}","{\"date\":\"2020-03-12\",\"open\":47.99,\"close\":45.54,\"high\":50.09,\"low\":45.37,\"volume\":50661745}"]}';
final parsedJson = json.decode(strJson);
print('${parsedJson.runtimeType} : $parsedJson');
}
main() {
test();
}
But getting this weird exception:
Unhandled exception:
FormatException: Unexpected character (at character 12)
{"ACB":["{"date":"2020-02-28","open":1.36,"close":1.34,"high":1.4,"low":1.3...
^
#0 _ChunkedJsonParser.fail (dart:convert-patch/convert_patch.dart:1394:5)
#1 _ChunkedJsonParser.parse (dart:convert-patch/convert_patch.dart:924:48)
#2 _parseJson (dart:convert-patch/convert_patch.dart:31:10)
#3 JsonDecoder.convert (dart:convert/json.dart:495:36)
#4 JsonCodec.decode (dart:convert/json.dart:153:41)
#5 test (file:///home/val/src/labs/maingain/test.dart:60:27)
#6 main (file:///home/val/src/labs/maingain/test.dart:65:3)
#7 _startIsolate.<anonymous closure> (dart:isolate-patch/isolate_patch.dart:307:19)
#8 _RawReceivePortImpl._handleMessage (dart:isolate-patch/isolate_patch.dart:174:12)
I'll just say, that running similar code from the Flutter seems to work fine. Only when running this from command line give me the above.
Also validated JSON.

Put an r in front of the string literal.
The '{"ACB":["{\"date\":....' is a plain single-quoted Dart string literal. That means that backslash is a string escape, so \" only adds " to the string value.
It's not a necessary escape because the string uses single quotes, but it's still treated like an escape.
That means that you pass the string content {"ACB":["{"date":... to the JSON decoder, which promptly gives up because the code is not valid JSON.
If you put an r in front of the string: r'{"ACB":["{\"date\":...' then the string literal becomes a raw string. That means that backslashes do not work as escapes, but are treated like literal characters. That makes the resulting string valid JSON.
Another alternative is to change every backslash to two: '{"ACB":["{\\"date\\":...'.

Related

Dart Higher-Order function with Generics

I'm trying to create a simple debug/print function that I can pipe through a sequence of then while processing Future results in Dart.
My function definition is as follows:
import 'dart:async';
typedef FutureOr<T> Pipe<T>(T pipeThrough);
Pipe<A> debug<A>(String log) {
return (A pipeThrough) {
print(log);
return pipeThrough;
};
}
It will return a function that just pipes through whatever it has received from the Future chain, and before that it will print the message log that has been sent to debug.
The way I'm using the function is quite simple:
Future<Map> load(String folder) {
return File(Paths.of([folder, 'data.json']))
.readAsString()
.then((s) => jsonDecode(s))
.then(debug<Map>('JSON LOADED!'));
}
As you can see in the last then in the future chain, it is supposed to return whatever was in the chain, but before that print 'JSON LOADED!'.
But there is something with the generics and Future api that I didn't manage to find a way to make it work, here's the error:
Unhandled exception:
type '(Map<dynamic, dynamic>) => Map<dynamic, dynamic>' is not a subtype of type '(dynamic) => FutureOr<Map<dynamic, dynamic>>'
#0 load (file:///{.../..../......}/data/data_json.dart:11:13)
#1 main (file:///{.../..../......}/data/main.dart:7:28)
#2 _startIsolate.<anonymous closure> (dart:isolate-patch/isolate_patch.dart:301:19)
#3 _RawReceivePortImpl._handleMessage (dart:isolate-patch/isolate_patch.dart:168:12)
I've tried a bunch of different things, but fundamentally I don't get what's happening, doesn't dart infer the proper types based on the generic types annotation?
I don't know why it can't handle the type here, but changing the code to
Future<Map> load(String folder) {
return File(Paths.of([folder, 'data.json']))
.readAsString()
.then((s) => jsonDecode(s))
.then((v) => debug<Map>('JSON LOADED!')(v));
}
fixes your issue. I had thought that this should be equivalent...

FormatException Invalid HTTP header Flutter on iOS

This code work's on Android device and emulator perfectly. On iOS emulator, doesn't work.
I try change String to lower case, remove spaces, etc, nothing resolve.
import 'package:http/http.dart' show Client;
...
Map<String,String> headers = Map();
headers['device'] = 'appleiphonexʀ';//'Apple-iPhone-Xʀ'//'Apple_iPhone_Xʀ'//'Apple iPhone Xʀ'
...
var response = await client.get(Uri.parse(url), headers: headers);
return await processResponse(response);
Throws Exception:
[VERBOSE-2:ui_dart_state.cc(148)] Unhandled Exception: FormatException: Invalid HTTP header field value: "appleiphonexʀ"
_HttpHeaders._validateValue (dart:_http/http_headers.dart:601:9)
_HttpHeaders._addAll (dart:_http/http_headers.dart:65:18)
_HttpHeaders.set (dart:_http/http_headers.dart:76:5)
IOClient.send.<anonymous closure> (package:http/src/io_client.dart:42:27)
__CompactLinkedCustomHashMap&_HashFieldBase&MapMixin&_LinkedHashMapMixin.forEach (dart:collection-patch/compact_hash.dart:367:8)
IOClient.send (package:http/src/io_client.dart:41:23)
< asynchronous suspension>
BaseClient._sendUnstreamed (package:http/src/base_client.dart:169:38)
< asynchronous suspension>
BaseClient.post (package:http/src/base_client.dart:54:7)
NetworkProvider.post (package:PROJECTXX/src/models/resources/network_provider.dart:24:22)
<asynchronous suspension>
Solved: see answer
The last character in your header is the Unicode code point hex 0280 aka LATIN LETTER SMALL CAPITAL R. According to RFC 2616, HTTP headers must only include characters in ISO-8859-1, unless they are encoded in a MIME format, which might look like =?UTF-8?Q?=E2=9C=B0?=. Could you instead use lower or uppercase ASCII R?
Follow Richard Heap comment, the problem was the last character, this data came from lib device_info: ^0.4.0+1
final DeviceInfoPlugin deviceInfoPlugin = new DeviceInfoPlugin();
PackageInfo packageInfo = await PackageInfo.fromPlatform();
...
var device = await deviceInfoPlugin.iosInfo.name;//Apple iPhone Xʀ
...
//the solution: remove non ascii chars and substitute for underline
headers['device'] = device.replaceAll(new RegExp('[^\u0001-\u007F]'),'_');

How to parse json data if it has escape characters in response with dart or flutter?

my json response is {"quoteText":"You\'re not obligated to win. You\'re obligated to keep trying to do the best you can every day.", "quoteAuthor":"Marian Edelman"} and I am trying to decode by Map<String, dynamic> quoteData = jsonDecode(response.body); but getting this exception
[ERROR:flutter/shell/common/shell.cc(184)] Dart Error: Unhandled exception:
E/flutter ( 5814): FormatException: Unrecognized string escape (at character 20)
E/flutter ( 5814): {"quoteText":"You\'re not obligated to win. You\'re obligated to keep tryin...
E/flutter ( 5814): ^
E/flutter ( 5814):
E/flutter ( 5814): #0 _ChunkedJsonParser.fail (dart:convert/runtime/libconvert_patch.dart:1358:5)
Tried by json.decode() and by doing flutter-remove-escape-sequence-in-dart but no luck. Any workaround?
That isn't valid json. Single quotes should not be escaped. Either you should get the source to fix it, or you can try to fix the string yourself by wholesale replacing any occurrence of \' with '.
String fixed = badString.replaceAll(r"\'", "'");
json.decode(fixed);

How to escape regex string

I have the following regex string used for determining a valid email address (including special characters e.g. ö, ê, ī, etc):
^(([^<>()[\]\\.,;:\s#\"]+(\.[^<>()[\]\\.,;:\s#\"]+)*)|(\".+\"))#((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$
It's tested on https://regex101.com as working regex. I then want to include this string in my code so I have to escape it. I therefore ended up with the following string:
^(([^<>()[\\]\\\\.,;:\\s#\\\"]+(\\.[^<>()[\\]\\\\.,;:\\s#\\\"]+)*)|(\\\".+\\\"))#((\\[[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\])|(([a-zA-Z\\-0-9]+\\.)+[a-zA-Z]{2,}))$
Now, when I run my code:
private static func regexMatch(regex: String, string: String) -> Bool {
let stringTest = NSPredicate(format:"SELF MATCHES %#", regex)
return stringTest.evaluateWithObject(string)
}
My app crashes with the following error:
*** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Can't do regex matching, reason: Can't open pattern U_REGEX_MISSING_CLOSE_BRACKET (string scött.hôdśōn#example.com, pattern ^(([^<>()[]\.,;:\s#\"]+(.[^<>()[]\.,;:\s#\"]+)*)|(\".+\"))#(([[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}])|(([a-zA-Z-0-9]+.)+[a-zA-Z]{2,}))$, case 0, canon 0)'
My guess is I am somehow escaping the regex string incorrectly. Can somebody point me in the right direction?
The comments about actually improving your regex should probably be heeded. There were a few things you were not escaping when you should, specifically ] and escaping when you didnt need to, specifically . inside [] and ". After fixing these in your regex
^(([^<>()[\].,;:\s#"]+(.[^<>()[\].,;:\s#"]+)*)|(".+"))#(([[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}])|(([a-zA-Z-0-9]+.)+[a-zA-Z]{2,}))$
And then escaping for special characters, we get
"/^(([^<>()[\\].,;:\\s#\"]+(.[^<>()[\\].,;:\\s#\"]+)*)|(\".+\"))#(([[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}])|(([a-zA-Z-0-9]+.)+[a-zA-Z]{2,}))$/"
I suspect the "missing bracket" error was caused by the improper escaping of ] which prematurely closed some alternator blocks you had. Again, the commentators on your post are correct that the regex itself could definitely be improved
I updated my regex string to the following and now it seems to be working.
^([^x00-\\\\x7F]|[\\w-\\.])+#((([^x00-\\\\x7F]|)[\\w-])+\\.)+[\\w-]{2,4}$

What is the true meaning of pass-by-reference in modern languages like Dart?

Working with Futures in Dart, I've come across an interesting issue.
import 'dart:async';
class Egg {
String style;
Egg(this.style);
}
Future cookEggs(List<Egg> list) =>
new Future(() =>
['omelette','over easy'].forEach((_) => list.add(new Egg(_)))
);
Future cookOne(Egg egg) => new Future(() => egg = new Egg('scrambled'));
void main() {
List<Egg> eggList = new List();
Egg single;
cookEggs(eggList).whenComplete(() => eggList.forEach((_) => print(_.style));
cookOne(single).whenComplete(() => print(single.style));
}
The expected output is:
omelette
over easy
scrambled
The cookEggs function that gets the List<Eggs> works fine, but accessing the style property of single is unsuccessful and throws a NoSuchMethodError.
I first thought that this might have something to do with pass-by-reference, but I don't see why Dart would pass a List by reference but not an Egg. Now I'm thinking that the discrepancy may have something to do with the assignment (=) operator and the List.add() method. I'm stuck in that train of thought, and I don't know how to test my hypothesis.
Any thoughts?
The program's output and stack trace is show below:
omelette
over easy
Uncaught Error: The null object does not have a getter 'style'.
NoSuchMethodError: method not found: 'style'
Receiver: null
Arguments: []
Stack Trace:
#0 Object.noSuchMethod (dart:core-patch/object_patch.dart:45)
#1 main.<anonymous closure> (file:///path/to/eggs.dart:20:51)
#2 _rootRun (dart:async/zone.dart:719)
#3 _RootZone.run (dart:async/zone.dart:862)
#4 _Future._propagateToListeners.handleWhenCompleteCallback (dart:async/future_impl.dart:540)
#5 _Future._propagateToListeners (dart:async/future_impl.dart:577)
#6 _Future._complete (dart:async/future_impl.dart:317)
#7 Future.Future.<anonymous closure> (dart:async/future.dart:118)
#8 _createTimer.<anonymous closure> (dart:async-patch/timer_patch.dart:11)
#9 _handleTimeout (dart:io/timer_impl.dart:292)
#10 _RawReceivePortImpl._handleMessage (dart:isolate-patch/isolate_patch.dart:124)
Unhandled exception:
The null object does not have a getter 'style'.
NoSuchMethodError: method not found: 'style'
Receiver: null
Arguments: []
#0 _rootHandleUncaughtError.<anonymous closure>.<anonymous closure> (dart:async/zone.dart:713)
#1 _asyncRunCallbackLoop (dart:async/schedule_microtask.dart:23)
#2 _asyncRunCallback (dart:async/schedule_microtask.dart:32)
#3 _asyncRunCallback (dart:async/schedule_microtask.dart:36)
#4 _RawReceivePortImpl._handleMessage (dart:isolate-patch/isolate_patch.dart:128)
Quick answer: what gets passed to your functions cookEggs and cookOne are references to the objects, not to the variables (which would be real pass-by-reference).
The term pass-by-reference is often misused to mean pass-references-by-value: many languages only have pass-by-value semantics, where the values that are passed around are references (i.e. pointers, without the dangerous features). See Is Java "pass-by-reference" or "pass-by-value"?
In the case of cookEggs(eggList)…
…the variable eggList contains a reference to a list of eggs. That reference was initially given to you by the expression new List(), and you're passing it to cookEggs after storing meanwhile in your variable eggList. Inside cookEggs, adding to the list works, because you passed a reference to an actual, existing list object.
In the case of cookOne(single)…
…the variable single has only been declared, so it was implicitly initialized by the language runtime to the special reference null. Inside cookOne, you're replacing which reference is contained in egg; since single is a different variable, it still contains null, therefore the code fails when you try to use that.
To clarify
The pass-references-by-value behavior is common to a lot of modern languages (Smalltalk, Java, Ruby, Python…). When you pass an object, you're actually passing-by-value (therefore copying) the contents of your variable, which is a pointer to the object. You never control where objects really exist.
Those pointers are named references rather than pointers, because they are restricted to abstract away the memory layout: you can't know the address of an object, you can't peek at the bytes around an object, you can't even be sure that an object is stored at a fixed place in memory, or that it's stored in memory at all (one could implement object references as UUIDs or keys in a persistent database, as in Gemstone).
In contrast, with pass-by-reference, you'd conceptually pass the variable itself, not its contents. To implement pass-by-reference in a pass-by-value language, you would need to reify variables as ValueHolder objects that can be passed around and whose contents can be changed.
That's because, like Java, Dart is always pass-by-value, and never pass-by-reference. The semantics of passing and assigning in Dart is the same as in Java. Look anywhere on StackOverflow about Java and pass by value to see why Java is described as always pass-by-value. Terms like pass-by-value and pass-by-reference should be used consistently across languages. So Dart should be described as always pass-by-value.
In actual "pass-by-reference", e.g. when a parameter is marked with & in C++ or PHP, or when a parameter is marked with ref or out in C#, simple assignment (i.e. with =) to that parameter variable inside the function will have the same effect as simple assignment (i.e. with =) to the original passed variable outside the function. This is not possible in Dart.
A popular misconception is that Dart is pass-by-reference. However, in a true pass-by-reference system (supported by languages such as C++), a function can set (and not just mutate) local variables in the caller.
Dart, like many other languages (e.g. Java, Python), is technically pass-by-value where the "value" of an object is a reference to it. This is why functions can mutate arguments passed by the caller.
However, in these languages where everything is an object and where there are not separate pointer types, "pass-by-value" and "pass-by-reference" can be confusing terms and are not particularly meaningful. A lot of Python programmers instead use the term pass-by-assignment.
Pass-by-assignment means that arguments are passed in way that's equivalent to normal variable assignment. For example, if I had:
final int x = 42;
final String s = "hello world!";
void foo(int intArgument, String stringArgument) {
...
}
void main() {
foo(x, s);
}
then the behavior would be equivalent to:
final int x = 42;
final String s = "hello world!";
void foo() {
int intArgument = x;
String stringArgument = s;
...
}
void main() {
foo();
}
When you do String stringArgument = s;, stringArgument and s are two separate variables referring to the same object. Reassigning stringArgument to something else won't change what s refers to. However, if you mutate that object in place, both stringArgument and s will refer to the now modified object.

Resources