Как преобразовать объект JavaScript в Dart Map?

Я ищу несколько обратных new JsObject.jsify. Что-то, что преобразует javascript Object обратно в Dart Map Есть ли что-то вроде этого?

Я знаю, что я могу использовать преобразование JSON в строку, но это не касается переноса Object содержащих функций, объектов Dart, элементов Dom и т.д. Есть ли лучший метод?

Ответы

Ответ 1

Здесь адаптер для обработки JsObject как 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);
}

Ответ 2

Если вы хотите сделать это глубоко и обрабатывать также другие случаи, тогда простые карты AND сохраняют функции (в отличие от решения json), то используйте эту простую функцию:

_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;
 }
}

Ответ 3

Вы можете генерировать json и анализировать его:

    Map map = JSON.decode(
       context['JSON'].callMethod(
           'stringify',
           [context['map']]
       )
    );

Ответ 4

Все приведенные выше ответы не помогли мне.

matanlurey предоставила решение, которое кажется более актуальным и фактически сработало для меня (Dart SDK 1.24.0), здесь:

fooobar.com/questions/353066/...

Это очень похоже в двух словах, но вместо dart:js используется новый package:js.

Ответ 5

Преобразует рекурсивно любой объект JS в карту Дарта, список или скалярное значение:

/// 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]);

Использование:

/// 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');
}

Предостережения: созданный экземпляр не отражает изменения исходного объекта JS. Если вам нужна эта функция, ответ Alexandre Arduin правильный.