Function that converts this string to json

5

I have string in the following format:

"a=123 b="ABC" c="Olá Mundo!""

I need to create a function that transforms this string into this json:

{
    a : 123,
    b : "ABC",
    c : "Olá Mundo!"
}

I think it has a bit of regular expression and a split (), but I know almost nothing about RegEx.

I was developing this function, but I did not get much success.

    function strToJson(str) {
        var json = {};
        var str_split = str.split(" ");
        var str_split_value = [];

        for (var i in str_split) {
            str_split_value = str_split[i].split("=");
            json[str_split_value[0]] = str_split_value[1];
        }

        return json;
    }

    console.log(strToJson('a=123 b="ABC" c="Olá Mundo!"'));
    
asked by anonymous 10.06.2016 / 02:16

3 answers

2

Everything is easier with REGEX.

([a-zA-Z_]\w*?)=(\d+|"[^"]*")( |$)

Explanation

([a-zA-Z_]\w*?)

Part of variable name - Group 1

  • [a-zA-Z_] = will ensure you start with a letter or underline
  • \w*? = allows you to have more letters numbers and underline

(\d+|"[^"]*")

Part of the content - Group 2

  • \d+ = must capture numbers
  • | = OU wants to say that if the previous crash tries the next one
  • "[^"]*" = Must catch a " anything other than " and finally a " - a string

Part of term - Group 3 (not useful for use)

Use

'a=123 b="ABC" c="Olá Mundo!"'.match(/([a-zA-Z_]\w*?)=(\d+|"[^"]*")( |$)/g)

See working at REGEX101

    
10.06.2016 / 14:41
5
var s = 'a=123 b="ABC" c="Olá Mundo!"';

var obj = {},
    parcial = '',
    inString = false,
    isProp = true,
    conteudo = '',
    prop = '';
for (i = 0; i < s.length; i++) { 
    var atual = s[i];

    if(atual=='"'){
        inString = !inString;
    }

    if((atual==' ')&&(!inString)){
        isProp=true;
        parcial='';
        obj[prop]=conteudo;
        continue;
    }
    if(atual == '='){
        isProp=false;
        parcial='';
        continue;
    }

    parcial += atual;
    if(isProp){
        prop=parcial;
    } else {
        conteudo=parcial;
    }

    if(i==s.length-1){
        obj[prop]=conteudo;
    }

    console.log('Atual: "'+atual+'"; Parcial: "'+parcial+'"; Prop:"'+prop+'"; Conteudo:"'+conteudo+'";');

}

console.log(obj);
    
10.06.2016 / 03:36
3

No split () or simple regular expression will do what you want. You need to develop a mini-interpreter, with state machine. Something in this style (in pseudocode):

estado = 0;
nome = "";
valor = "";

// sentinela para terminar o parse dentro do loop
str += " ";

for (i = 0; i < str.length(); ++i) {
    // interpreta caractere por caractere
    c = str[i];
    if (estado === 0) {
        // estado: inicial
        c é espaço -> ignora
        c é letra -> estado := 1
                      nome := c
        c de outro tipo -> erro! 
    } else if (estado === 1) {
        // estado: acumulando nome 
        c é letra, número ou _ -> nome += c
        c é "=" -> estado := 2
        c é outro tipo -> erro!
    } else if (estado === 2) {
        // estado: = encontrado
        c é número -> valor := c
                      estado := 3
        c é aspa -> valor := c
                    estado := 4
        c é espaço -> ignora
        c é outra coisa -> erro! 
    } else if (estado === 3) {
        // estado: acumulando valor inteiro
        c é número -> valor += c
        c é espaço -> grava tupla (nome, parseInt(valor))
                      estado := 0
        c é outra coisa -> erro!
    } else if (estado === 4) {
        // estado: acumulando string 
        c é aspa -> grava tupla (nome, valor)
                    estado := 0
        c é qualquer outro caractere -> valor += c
    }
}
    
10.06.2016 / 03:04