2
votes

I'm writing a custom dart to js interop around chrome.storage.local.set using new js package and dart 2 SDK.

A Map in Dart is not the same thing as an object in JavaScript, but forcing developers to write abstract classes every-time they want to use a public facing API is not the right thing either.

So, I'm looking for a way to convert dart Map to a JavaScript object that won't require writing abstract class.

Using dart:js it was easy to convert a dart Map to JS object but with new js package I have not seen any example that dynamically converts dart Map to js object.

2

2 Answers

5
votes

I was able to solve this problem by writing this function that converts a Map to js object.

import 'package:js/js_util.dart' as js;
Object mapToJSObj(Map<dynamic,dynamic> a){
  var object = js.newObject();
  a.forEach((k, v) {
    var key = k;
    var value = v;
    js.setProperty(object, key, value);
  });
  return object;
}
4
votes

A slightly modified version of the accepted answer, which also handles nested Maps. And I also added a solution for convering the other way: from a Javascript object to a Dart Map.

import 'package:js/js.dart';
import 'package:js/js_util.dart';

Object mapToJsObject(Map map){
  var object = newObject();
  map.forEach((k, v) {
    if (v is Map) {
      setProperty(object, k, mapToJsObject(v));
    } else {
      setProperty(object, k, v);
    }
  });
  return object;
}

Map jsObjectToMap(dynamic jsObject) {
  Map result = {};
  List keys = _objectKeys(jsObject);
  for (dynamic key in keys) {
    dynamic value = getProperty(jsObject, key);
    List nestedKeys = objectKeys(value);
    if ((nestedKeys ?? []).isNotEmpty) {
      //nested property
      result[key] = jsObjectToMap(value);
    } else {
      result[key] = value;
    }
  }
  return result;
}

List<String> objectKeys(dynamic jsObject) {
  if (jsObject == null || jsObject is String || jsObject is num || jsObject is bool) return null;
  return _objectKeys(jsObject);
}

@JS('Object.keys')
external List<String> _objectKeys(jsObject);