Search code examples
dartnull-safety

Null aware assignment of map entry


Is there an elegant way to write the following statement for a map?

  String? img = json['image'];
  if (img != null) {
    json['image'] = 'https://example.com/ingredients_100x100/' + img;
  }

Basically I want to append the image IFF it exists and ignore if it does not. This has the opposite effect of ??= where the assignment occurs only if the image is found to be null. Which is similar to putIfAbsent.

The best I can come up with is this:

String? img = json['image'];
json['image'] = img != null ? 'https://example.com/ingredients_100x100/' + img : null;

I just feel like this is the wrong way of writing for null safety as the word null appears twice in a line.


Solution

  • You could also use the update method of Map. It will throw an error if the key 'image' does not exist. With the update method, you can also easily provide a default if the key image does not exist.

    const baseImgUrl = 'https://example.com/ingredients_100x100/';
    const defaultImgFilename = 'default.png';
    
    Map<String, dynamic> updateImage(Map<String, dynamic> json) {
      try {
        return json
          ..update(
            'image',
            (filename) => '$baseImgUrl$filename',
          );
      } catch (_) { // key not in map
        return json;
      }
    }
    
    Map<String, dynamic> updateImageWithDefault(Map<String, dynamic> json) {
        return json
          ..update(
            'image',
            (filename) => '$baseImgUrl$filename',
            ifAbsent: () => '$baseImgUrl$defaultImgFilename',
          );
    }
    
    void main() {
      Map<String, dynamic> jsonWithoutImage = {'data': 123};
    
      updateImage(jsonWithoutImage);
      print('JSON without image: $jsonWithoutImage');
      // JSON without image: {data: 123}
      
      updateImageWithDefault(jsonWithoutImage);
      print('JSON with default image: $jsonWithoutImage');
      // JSON with default image: {data: 123, image: https://example.com/ingredients_100x100/default.png}
    
      Map<String, dynamic> jsonWithImage = {'data': 123, 'image': 'apple.png'};
      
      updateImage(jsonWithImage);
      print('JSON with image: $jsonWithImage');
      // JSON with image: {data: 123, image: https://example.com/ingredients_100x100/apple.png}
    }