95

I wanted to convert a string to map.

String value = "{first_name : fname,last_name : lname,gender : male, location : { state : state, country : country, place : place} }"

into

Map = {
first_name : fname,
last_name : lname,
gender : male,
location = {
  state : state, 
  country : country, 
  place : place
 }
}

How do I convert the string into a map<String, dynamic> where the value consists of string, int, object, and boolean?

I wanted to save the string to a file and obtain the data from the file.

Günter Zöchbauer
  • 623,577
  • 216
  • 2,003
  • 1,567
Daniel Mana
  • 9,451
  • 13
  • 29
  • 41

9 Answers9

167

That's not possible.

If you can change the string to valid JSON, you can use

import 'dart:convert';
...
Map valueMap = json.decode(value);
// or
Map valueMap = jsonDecode(value);

The string would need to look like

{"first_name" : "fname","last_name" : "lname","gender" : "male", "location" : { "state" : "state", "country" : "country", "place" : "place"} }
CopsOnRoad
  • 237,138
  • 77
  • 654
  • 440
Günter Zöchbauer
  • 623,577
  • 216
  • 2,003
  • 1,567
  • 14
    If you are saving an existing map, you can likely convert that map to a valid JSON string using `json.encode`, then it will parse back correctly using `json.decode`. – lrn Apr 06 '18 at 10:01
  • how can i covert this type of string to map [{type: Input, title: Hi Group, placeholder: Hi Group flutter, response: fgggh}, {type: Password, title: Password, response: vvvvv}, {type: Email, title: Email test, placeholder: hola a todos, response: cccvc}, {type: TareaText, title: TareaText test, placeholder: hola a todos, response: vvvvv}] – Hitanshu Gogoi Jan 04 '19 at 06:45
  • 3
    What you posted is not JSON. In JSON all keys and string values would need quotes. If it were valid JSON you could use `var decoded = json.decode(yourString); var map = Map.fromIterable(decoded, key: (e) => e.keys.first, value: (e) => e.values.first);` (not tested). See also https://api.dartlang.org/stable/2.1.0/dart-core/Map/Map.fromIterable.html – Günter Zöchbauer Jan 04 '19 at 06:50
41

You would have to change the way you create the string.

I'm guessing you are creating the string using the yourMap.toString() method. You should rather use json.encode(yourMap), which converts your map to valid JSON, which you can the parse with json.decode(yourString).

leodriesch
  • 5,308
  • 5
  • 30
  • 52
7

create two objects

class User {
  final String firstName;
  final String lastName;
  final String gender;
  final location;

  User({
    this.firstName,
    this.lastName,
    this.gender,
    this.location,
  });

  User.fromJson(Map json)
      : firstName = json['firstName'],
        lastName = json['lastName'],
        gender = json['gender'],
        location = Location.fromJson(json['location']);
}

class Location {
  final String state;
  final String country;
  final String place;

  Location({
    this.state,
    this.country,
    this.place,
  });

  Location.fromJson(Map json)
      : state = json['state'],
        country = json['country'],
        place = json['place'];
}

then use it like this

var user = User.fromJson(value);
print(user.firstName);

or convert it to list like this

var user = User.fromJson(value).toList();
Patrioticcow
  • 26,422
  • 75
  • 217
  • 337
  • Thank you so much for your solution, I was getting error because I was using **.toString** instead of **jsonEncode** – Azhar Ali Sep 14 '21 at 09:51
5

you can do like this ->

import 'dart:convert'; ...

if your data like this ** {'bus1':'100Tk','bus2':'150TK','bus3':'200TK'}

**;

then you can do like this ->

Map valueMap = json.decode(value);

// or

Map valueMap = jsonDecode(value);

or if like this ->var data = {'1':'100TK','2':'200TK','3':'300TK'};

var dataSp = data.split(',');
Map<String,String> mapData = Map();
dataSp.forEach((element) => mapData[element.split(':')[0]] = element.split(':')[1]);

Note: Map first value was Int that's why I did that.

Rasel Khan
  • 2,976
  • 19
  • 25
4

Make a wrapper class for the location where you define the methods fromMap, toMap

doomkin
  • 41
  • 2
2

Yeah, that's not possible.

But i have workaround to fix that.

  • Remove space in ur invalid json
  • Fix ur invalid string json to valid string json
  • Convert valid string json to map

Here's the full code for above process:

import 'dart:convert';

void main() {
  String value = "{first_name : fname,last_name : lname,gender : male, location : { state : state, country : country, place : place} }";
  
  String jsonString = _convertToJsonStringQuotes(raw: value);
  print("Test 1: $jsonString");
  
  final Map<dynamic, dynamic> result = json.decode(jsonString);
  print('Test 2: $result');
}


String _convertToJsonStringQuotes({required String raw}) {
    /// remove space
    String jsonString = raw.replaceAll(" ", "");

    /// add quotes to json string
    jsonString = jsonString.replaceAll('{', '{"');
    jsonString = jsonString.replaceAll(':', '": "');
    jsonString = jsonString.replaceAll(',', '", "');
    jsonString = jsonString.replaceAll('}', '"}');

    /// remove quotes on object json string
    jsonString = jsonString.replaceAll('"{"', '{"');
    jsonString = jsonString.replaceAll('"}"', '"}');

    /// remove quotes on array json string
    jsonString = jsonString.replaceAll('"[{', '[{');
    jsonString = jsonString.replaceAll('}]"', '}]');

    return jsonString;
  }
R Rifa Fauzi Komara
  • 1,915
  • 6
  • 27
  • 54
0
To convert a string into a map<String, dynamic>, you can use the

following code:

String value = "{first_name : fname,last_name : lname,gender : male, location : { state : state, country : country, place : place} }";
         String result = value
           .replaceAll("{","{\"")
           .replaceAll("}","\"}")
           .replaceAll(":","\":\"")
           .replaceAll(",","\",\"");
        print(result);

Here, we first replace the opening and closing curly braces with double quotes, and then replace the colons and commas with quotes to create a valid JSON string. Then, we use the jsonDecode method to convert the JSON string into a map.

waqas023
  • 5
  • 4
-1

I found a way to cast that string

Ok, lets use a complex model to cast:

final testMap = {
  'userName': 'Igor',
  'age': 22,
  'totalCash': 138.57,
  'isMale:': true,
  'userStatus': {
    'isUserActive': true,
    'isAPremiumUser': false,
  },
  'userTags': ['Flutter Developer', 'Proactive', 'Clean code'],
  'userCourses': [
    {
      'title': 'How to use TDD in flutter',
      'finished': false,
      'coursePercentage': 47.4,
      'buyDate': '1969-07-20T20:18:04.000Z',
      'courseTag': ['New', 'Popular'],
      'courseDetails': null,
    },
    {
      'title': 'Clean arquiteture in flutter',
      'finished': false,
      'coursePercentage': 20.8,
      'buyDate': '1969-07-20T20:18:04.000Z',
      'courseTag': ['New'],
      'courseDetails': {
        'teacherName': 'Tayler Mostoult',
        'totalSubscribers': 5402,
      },
    },
    {
      'title': 'Micro-frontends in flutter',
      'finished': true,
      'coursePercentage': 100.0,
      'buyDate': '1969-07-20T20:18:04.000Z',
      'courseTag': [],
      'courseDetails': {},
    },
  ]
};

Know, cast it to string:

final testMapInStringFormat = testMap.toString();

To convert this String to map, we can use:

// Decoded, back to map format
final Map response = _getJsonFromString(testMap.toString()); 

The function that will effectively do the casting:


  Map<String, dynamic> _getJsonFromString(String rawText) {
    // Will find, for exemple, the text: "{isUserActive:"
    final regexMapKeyWithOpenBracket = RegExp('(?<={)(.*?):+');
    // Will find, for exemple, the text: ", userCourses:"
    final regexMapKeyWithCommaAndSpace = RegExp(r'(?<=, )([^\]]*?):');

    final regexOnlyKeyInLine = RegExp(r'^.+:$');

    final splitedSentences = rawText
        .replaceAllMapped(regexMapKeyWithCommaAndSpace,
            (Match match) => '\n${match.text.trim()}\n')
        .replaceAllMapped(regexMapKeyWithOpenBracket,
            (Match match) => '\n${match.text.trim()}\n')
        .replaceAll(RegExp(r'}(?=,|]|}|$|\s+)'), '\n}\n')
        .replaceAll(RegExp(r'(?<=(,|:|^|\[)\s?){'), '\n{\n')
        .replaceAll(RegExp('\\[\\s?\\]'), '\n[\n]\n')
        .replaceAll(RegExp('\\{\\s?\\}'), '\n{\n}\n')
        .replaceAll('[', '\n[\n')
        .replaceAll(']', '\n]\n')
        .replaceAll(',', '\n,\n')
        .split('\n')
      ..removeWhere((element) => element.replaceAll(' ', '').isEmpty);

    final List<String> correctLines = [];
    for (String line in splitedSentences) {
      final isMapKey = regexOnlyKeyInLine.hasMatch(line);

      if (isMapKey) {
        final lineWithoutFinalTwoDots = line.substring(0, line.length - 1);
        final lineWithQuaot = _putQuotationMarks(lineWithoutFinalTwoDots);

        correctLines.add('$lineWithQuaot:');
      } else {
        String l = line.trim();

        final hasCommaInFinal = l.endsWith(',') && l.length > 1;
        if (hasCommaInFinal) l = l.substring(0, l.length - 1);

        // If it falls in this else, it is a value of a key or a map structure
        final isNumber = double.tryParse(l) != null || int.tryParse(l) != null;
        final isBolean = l == 'false' || l == 'true';
        final isStructureCaracter =
            ['{', '}', '[', ']', ','].any((e) => e == l);
        final isNull = l == 'null';
        if (isStructureCaracter || isNumber || isBolean || isNull) {
          if (hasCommaInFinal) {
            correctLines.add('$l,');
          } else {
            correctLines.add(l);
          }
          continue;
        }

        // If you got to this point, i'm sure it's a value string, so lets add a double quote
        final lineWithQuaot = _putQuotationMarks(l);
        if (hasCommaInFinal) {
          correctLines.add('$lineWithQuaot,');
        } else {
          correctLines.add(lineWithQuaot);
        }
      }
    }

    final Map<String, dynamic> decoded = {};
    (jsonDecode(correctLines.join('')) as Map)
        .cast<String, dynamic>()
        .forEach((key, value) {
      decoded[key] = value;
    });

    return decoded;
  }

extension MatchExtension on Match {
  String get text => input.substring(start, end);
}

String _putQuotationMarks(String findedText) {
  if (!findedText.startsWith('\'') && !findedText.startsWith('"')) {
    findedText = findedText[0] + findedText.substring(1);
  }
  if (!findedText.endsWith('\'')) {
    final lastIndex = findedText.length - 1;
    findedText = findedText.substring(0, lastIndex) + findedText[lastIndex];
  }
  return '"$findedText"';
}
Igor
  • 1
  • 1
-2

Use below method
just pass String json data it will give Map data

jsonStringToMap(String data){
      List<String> str = data.replaceAll("{","").replaceAll("}","").replaceAll("\"","").replaceAll("'","").split(",");
      Map<String,dynamic> result = {};
      for(int i=0;i<str.length;i++){
        List<String> s = str[i].split(":");
        result.putIfAbsent(s[0].trim(), () => s[1].trim());
      }
      return result;
    }
Mohit Modh
  • 335
  • 3
  • 4