Строка в массив объектов JS - PullRequest
0 голосов
/ 04 июня 2019

У меня есть строка, подобная этой:

"{id:1,another:thing},{id:2,another:item}"

Как я могу преобразовать это в JS в массив объектов [{...},{...}]?

РЕДАКТИРОВАТЬ

  • Многие в комментариях говорят, что строка не является допустимой JSON - я не утверждал, что это так.Я понимаю, хотя был вопрос JSON тег к вопросу.Мой плохой.
  • Я знаю, что могу отформатировать строку, похожую на JSON.У меня нет свободы изменять строку как таковую.
  • По двум вышеуказанным причинам вопрос отличается от предполагаемого дубликата.

Ответы [ 2 ]

3 голосов
/ 04 июня 2019

С этим форматом вы очень близки к конвертации в объект. Это не правильный JSON, но достаточно просто, если мы попытаемся решить проблему:

  1. Отделите объекты, чтобы из "{id:1,another:thing},{id:2,another:item}" мы могли получить массив, в котором каждый элемент является «объектом» и содержит только то, какими будут значения ключа -> поэтому каждый элемент равен «{id: 1, another: thing} «
  2. Затем каждая «строка объекта» фактически разделяется на строку для ключей и значений {id:1,another:thing} -> "id:1" и "another:thing"
  3. Значение ключа строки можно разбить на значение ключа пары : "id:1" -> "id" и "1".

Итак, это даст вам план со строительными блоками для каждого объекта и их ключами и значениями. Вот как это может работать как

let input = "{id:1,another:thing},{id:2,another:item}";

//capture objects like "{id:1,another:thing}"
const regexForObjects = /\{[^}]*\}/g;

let objectBlueprint = input
  .match(regexForObjects) //split off each "object" as a string
  .map(objString => objString.slice(1, -1)) //remove the first { and the last }
  .map(item => item.split(/\s*,\s*/)) // split each string representation of an object into strings for each key and value
  .map(item => item.map(subitem => subitem.split(/\s*:\s*/))) //split each key-value pair into a separate array.

console.log(objectBlueprint)

Это многословно - реализация может быть осуществлена ​​другими способами, но это дает представление о том, что происходит, следуя шагам.

как только это будет сделано, все, что осталось, это построить объекты из этого. Каждый объект представлен массивом, который содержит массивы пар ключ-значение, поэтому мы можем очень просто реализовать функцию, взять ее и вернуть объект:

let input = [ ["id", "1"], ["another", "thing"] ];

let output = fromArrayToObject(input);

console.log(output)

function fromArrayToObject(keyValuePairs) {
  return keyValuePairs.reduce((obj, [key, value]) => {
    obj[key] = value;
    
    return obj;
  }, {})
}

Прямо сейчас, это только производит строки как значения. Трудно догадаться, является ли "1" строкой или числом. Это работает как минимальная реализация, но вы также можете попытаться угадать тип значения:

let number = guessType("1");
let boolean = guessType("true");
let nul = guessType("null");
let string1 = guessType("The quick brown fox");
let string2 = guessType("something");

console.log("should be number:", typeof number);
console.log("should be boolean:", typeof boolean);
console.log("should be null:", nul === null); //typeof null -> "object", so doing an equality check
console.log("should be string:", typeof string1);
console.log("should be string:", typeof string2);

function guessType(value) {
  try {
    return JSON.parse(value)
  } catch (e) {
    return value;
  }
}

Это упрощенно, но может работать во многих ситуациях. Если строка может быть проанализирована в примитиве, то это тот примитив. Если этого не может быть, тогда он рассматривается как обычная строка.

Собрав все воедино, вот как это может выглядеть:

let input = "{id:1,another:thing},{id:2,another:item}";

//convert into the structure to build into objects
let objectBlueprint = input
  .match(/\{[^}]*\}/g)
  .map(objString => objString.slice(1, -1))
  .map(item => item.split(/\s*,\s*/))
  .map(item => item.map(subitem => subitem.split(/\s*:\s*/)));

//convert each object
let output = objectBlueprint.map(fromArrayToObject)

console.log(output);


function fromArrayToObject(keyValuePairs) {
  return keyValuePairs.reduce((obj, [key, value]) => {
    obj[key] = guessType(value);

    return obj;
  }, {})
}

function guessType(value) {
  try {
    return JSON.parse(value)
  } catch (e) {
    return value;
  }
}
1 голос
/ 04 июня 2019

Это не действительно JSON, поэтому JSON.parse не будет работать.Это не будет работать, потому что есть две большие проблемы с вашим JSON:1. это не массив, потому что элементы не окружены []2. Ключи и значения не окружены "

Попробуйте изменить JSON таким образом, чтобы он выглядел так:var jsonobject = '{"id":"1","another":"thing"},{"id":"2","another":"item"}';Затем вы можете добавить скобки, чтобы сделать его массивом, выполнив это:var json = '[' + jsonobject + ']';После этого вы можете использовать:JSON.parse(json);

Полный код:

var jsonobject = '{"id":"1","another":"thing"},{"id":"2","another":"item"}';
var json = '[' + jsonobject + ']';
var obj = JSON.parse(json);
// obj now got an js object array.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...