encode static method

String encode(
  1. Object? object, [
  2. EncodeOptions options = const EncodeOptions()
])

Encodes an Object into a query String. Providing custom options will override the default behavior.

Implementation

static String encode(
  Object? object, [
  EncodeOptions options = const EncodeOptions(),
]) {
  if (object == null) {
    return '';
  }

  late Map<String, dynamic> obj;
  if (object is Map<String, dynamic>) {
    obj = {...?object as Map<String, dynamic>?};
  } else if (object is Iterable) {
    obj = object.toList().asMap().map((k, v) => MapEntry(k.toString(), v));
  } else {
    obj = {};
  }

  final List keys = [];

  if (obj.isEmpty) {
    return '';
  }

  List? objKeys;

  if (options.filter is Function) {
    obj = options.filter?.call('', obj);
  } else if (options.filter is Iterable) {
    objKeys = List.of(options.filter);
  }

  final bool commaRoundTrip =
      options.listFormat.generator == ListFormat.comma.generator &&
          options.commaRoundTrip == true;

  objKeys ??= obj.keys.toList();

  if (options.sort is Function) {
    objKeys.sort(options.sort);
  }

  final WeakMap sideChannel = WeakMap();
  for (int i = 0; i < objKeys.length; i++) {
    final key = objKeys[i];
    if (key is! String?) {
      continue;
    }
    if (obj[key] == null && options.skipNulls) {
      continue;
    }

    final encoded = _$Encode._encode(
      obj[key],
      undefined: !obj.containsKey(key),
      prefix: key,
      generateArrayPrefix: options.listFormat.generator,
      commaRoundTrip: commaRoundTrip,
      allowEmptyLists: options.allowEmptyLists,
      strictNullHandling: options.strictNullHandling,
      skipNulls: options.skipNulls,
      encodeDotInKeys: options.encodeDotInKeys,
      encoder: options.encode ? options.encoder : null,
      serializeDate: options.serializeDate,
      filter: options.filter,
      sort: options.sort,
      allowDots: options.allowDots,
      format: options.format,
      formatter: options.formatter,
      encodeValuesOnly: options.encodeValuesOnly,
      charset: options.charset,
      addQueryPrefix: options.addQueryPrefix,
      sideChannel: sideChannel,
    );

    if (encoded is Iterable) {
      keys.addAll(encoded);
    } else {
      keys.add(encoded);
    }
  }

  final String joined = keys.join(options.delimiter);
  String prefix = options.addQueryPrefix ? '?' : '';

  if (options.charsetSentinel) {
    prefix += switch (options.charset) {
      /// encodeURIComponent('&#10003;')
      /// the "numeric entity" representation of a checkmark
      latin1 => '${Sentinel.iso}&',

      /// encodeURIComponent('✓')
      utf8 => '${Sentinel.charset}&',
      _ => '',
    };
  }

  return joined.isNotEmpty ? prefix + joined : '';
}