8

How to convert an Object type to a Map type (array) in Dart, so the variables become key/value pairs?

2 Answers 2

2
/**
   * Uses refection (mirrors) to produce a Map (array) from an object's
   * variables. Making the variable name the key, and it's value the
   * value.
   */
  Map objectToMap(Object object)
  {
    // Mirror the particular instance (rather than the class itself)
    InstanceMirror instanceMirror = reflect(object);
    Map dataMapped = new Map();

    // Mirror the instance's class (type) to get the declarations
    for (var declaration in instanceMirror.type.declarations.values)
    {
      // If declaration is a type of variable, map variable name and value
      if (declaration is VariableMirror)
      {
        String variableName = MirrorSystem.getName(declaration.simpleName);
        String variableValue = instanceMirror.getField(declaration.simpleName).reflectee;

        dataMapped[variableName] = variableValue;
      }
    }

    return dataMapped;
  }
Sign up to request clarification or add additional context in comments.

1 Comment

Note this is ok for server side code, but using mirrors with dart2js is not recommended. The smoke package can help with this use case. It uses mirrors when running in Dartium, but uses code generation when running with dart2js.
0

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, see: https://stackoverflow.com/a/20720378/1084485

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.