How to convert JavaScript object to Dart Map?

后端 未结 5 615
梦毁少年i
梦毁少年i 2021-01-04 02:24

I am looking for some reverse of new JsObject.jsify. Something, that would convert javascript Object back to Dart Map Is there somethi

相关标签:
5条回答
  • 2021-01-04 02:37

    All of the above answers didn't work for me.

    matanlurey provided a solution which seems more up to date and actually worked for me (Dart SDK 1.24.0), here:

    https://stackoverflow.com/a/41291503/5280562

    It's very similar in a nutshell but uses the new package:js instead of dart:js.

    0 讨论(0)
  • 2021-01-04 02:46

    Will convert recursively any JS object to a Dart map, list or scalar value:

    /// js_interop.dart
    import 'dart:js';
    
    /// Converts the specified JavaScript [value] to a Dart instance.
    dynamic convertToDart(value) {
      // Value types.
      if (value == null) return null;
      if (value is bool || value is num || value is DateTime || value is String) return value;
    
      // JsArray.
      if (value is Iterable) return value.map(convertToDart).toList();
    
      // JsObject.
      return new Map.fromIterable(getKeysOfObject(value), value: (key) => convertToDart(value[key]));
    }
    
    /// Gets the enumerable properties of the specified JavaScript [object].
    List<String> getKeysOfObject(JsObject object) => (context['Object'] as JsFunction).callMethod('keys', [object]);
    

    Usage:

    /// config.js
    window.$environment = 'staging';
    window.$config = {
      name: 'FooBar',
      params: {
        assets: ['css', 'js'],
        forceSsl: true
      }
    };
    
    /// main.dart
    import 'dart:js' as js;
    import 'js_interop.dart';
    
    void main() {
      var environment = convertToDart(js.context[r'$environment']);
      assert(environment is String);
      assert(environment == 'staging');
    
      var config = convertToDart(js.context[r'$config']);
      assert(config is Map<String, dynamic>);
      assert(config.length == 2);
    
      assert(config['name'] is String);
      assert(config['name'] == 'FooBar');
    
      assert(config['params'] is Map<String, dynamic>);
      assert(config['params'].length == 2);
    
      assert(config['params']['forceSsl'] is bool);
      assert(config['params']['forceSsl'] == true);
    
      assert(config['params']['assets'] is List<String>);
      assert(config['params']['assets'].length == 2);
      assert(config['params']['assets'].first == 'css');
      assert(config['params']['assets'].last == 'js');
    }
    

    Caveats: the created instance does not reflect the changes from the original JS object. If you need this feature, Alexandre Arduin's answer is the right one.

    0 讨论(0)
  • 2021-01-04 02:56

    Here's an adapter to handle a JsObject like a Map<String, dynamic> :

    import 'dart:collection' show Maps;
    import 'dart:js';
    
    class JsMap implements Map<String,dynamic> {
      final JsObject _jsObject;
      JsMap.fromJsObject(this._jsObject);
    
      operator [](String key) => _jsObject[key];
      void operator []=(String key, value) {
        _jsObject[key] = value;
      }
      remove(String key) {
        final value = this[key];
        _jsObject.deleteProperty(key);
        return value;
      }
      Iterable<String> get keys => context['Object'].callMethod('keys', [_jsObject]);
    
      // use Maps to implement functions
      bool containsValue(value) => Maps.containsValue(this, value);
      bool containsKey(String key) => keys.contains(key);
      putIfAbsent(String key, ifAbsent()) => Maps.putIfAbsent(this, key, ifAbsent);
      void addAll(Map<String, dynamic> other) {
        if (other != null) {
          other.forEach((k,v) => this[k] = v);
        }
      }
      void clear() => Maps.clear(this);
      void forEach(void f(String key, value)) => Maps.forEach(this, f);
      Iterable get values => Maps.getValues(this);
      int get length => Maps.length(this);
      bool get isEmpty => Maps.isEmpty(this);
      bool get isNotEmpty => Maps.isNotEmpty(this);
    }
    
    0 讨论(0)
  • 2021-01-04 02:58

    If you want to do it deeply and handle also other cases then simple maps AND preserve functions (unlike the json solution) then use this simple function:

    _toDartSimpleObject(thing) {
     if (thing is js.JsArray) {
      List res = new List();
      js.JsArray a = thing as js.JsArray;
      a.forEach((otherthing) {
        res.add(_toDartSimpleObject(otherthing));
      });
      return res;
    
     } else if (thing is js.JsObject) {
      Map res = new Map();
      js.JsObject o = thing as js.JsObject;
      Iterable<String> k = js.context['Object'].callMethod('keys', [o]);
       k.forEach((String k) {
       res[k] = _toDartSimpleObject(o[k]);
      });
      return res;
    
     } else {
      return thing;
     }
    }
    
    0 讨论(0)
  • 2021-01-04 03:01

    You can generate json and parse it:

        Map map = JSON.decode(
           context['JSON'].callMethod(
               'stringify',
               [context['map']]
           )
        );
    
    0 讨论(0)
提交回复
热议问题