Работа с объектами после JSON parse

325
26 ноября 2016, 17:51

Всем привет. Есть такой код:

class User {
    constructor(id, username, date){
        this.id = id;
        this.username = username;
        this.date= date;
    }
}
let myUsers = [
    new User(1, 'Mark', new Date('03.01.2016')),
    new User(2, 'Jacob', new Date('02.02.2016')),
    new User(3, 'Petr', new Date('01.02.2016'))
];

Я превращаю этот массив в JSON и храню в локальном хранилище.

localStorage.setItem('myUsers', JSON.stringify(myUsers));

Затем достаю и выполняю парсинг

let users = localStorage.getItem('myUsers');
users = JSON.parse(users);

Когда я пытаюсь вывести отформатированную дату

users.forEach(function(user){
  console.log(user.date.getDate());
});

сообщает об ошибке

Uncaught TypeError: user.date.getDate is not a function

Я так понимаю это происходит потому что после парсинга я получаю строку, а не объект с датой. Собственно в этом и вопрос. Как получить возможность работать со свойствами объекта в данном случае?

Answer 1

JSON.stringify() Функции не являются допустимыми данными в JSON, так что они не будут работать. Кроме того, некоторые объекты, например, объект Date, станут строками после применения JSON.parse().

JSON.stringify(myUsers) создаст JSON-строку, которая будет выглядеть следующим образом:

"[{"id":1,"username":"Mark","date":"2016-02-29T17:00:00.000Z"},{"id":2,"username":"Jacob","date":"2016-02-01T17:00:00.000Z"},{"id":3,"username":"Petr","date":"2016-01-01T17:00:00.000Z"}]"

Т.е. у каждого объекта User будет сохранены свойста string, number, boolean, object и array. И после выполения JSON.parse вы получаете массив объектов Object (не User) с полями id, username, date.

[Object, Object, Object]

Т.е. нужен метод для создания объектов User (что-то наподобии десериализации получится)

class User {
  constructor(id, username, date){
    this.id = id;
    this.username = username;
    this.date = date;
  }
  static fromJson(json) {
    var data = JSON.parse(json); // Парсим поля
    var date = new Date(data.date); // создает объект Date из строки
    return new User(data.id, data.username, date); // Создаем новый инстанс
  }
};
Пример использования:
const user1 = new User(1, 'Mark', new Date('03.01.2016'));
const serialize = JSON.stringify(user1); //.toJson();
const _user1 = User.fromJson(serialize);
console.log(_user1.date.getDate()); // 1

Для "сериализации" только нужных свойств, можно написать так же метод toJson, внутри которого уже вызывать JSON.stringify

Answer 2

В JSON.parse() можно вторым параметром передать функцию, которая будет вызвана для каждой пары ключ-значение:

const dateFormat = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}Z$/;
function reviver(key, value) {
    if (typeof value === "string" && dateFormat.test(value)) {
        return new Date(value);
    }
    return value;
}
const text = '{ "date": "2016-04-26T18:09:16Z" }';
const obj = JSON.parse(text, reviver);

Источник.

Или, если вы знаете как называется название свойства, в котором хранится дата, то можно просто проверять значение аргумента key.

Аналогично, вы можете трансформировать результаты разбора JSON в любой нужный вам объект.

READ ALSO
Не передается link-url d GTM v2

Не передается link-url d GTM v2

Не могу настроить отслеживание кликов по кнопкам в GTM, все что отображается в слое данных - это класс , а класс указанный для ссылки он не видит,...

259
Как сделать редирект в js?

Как сделать редирект в js?

Доброго времени суток! Возникла такая проблемаНе работает редирект в js

250
Передача значения из формы в javascript

Передача значения из формы в javascript

Есть расширения chromeВ самом расширении ссылка на страницу настроек с формой

314
Не правильно работает календарь

Не правильно работает календарь

Задание: Нужно сделать так, чтобы в поле можно было ввести дату не меньше чем послезавтрашний день и не больше чем на пол года больше, например...

237