Javascript-форум (https://javascript.ru/forum/)
-   Общие вопросы Javascript (https://javascript.ru/forum/misc/)
-   -   Помогите ламеру распарсить json (https://javascript.ru/forum/misc/80500-pomogite-lameru-rasparsit-json.html)

lolka84 13.06.2020 14:15

Помогите ламеру распарсить json
 
Привет, сто лет не связывался с js, но тут прижало..
Суть такая: кидаю ajax'ом запрос, получаю данные. Их нужно распарсить.
Приходит json такого типа:

Код:

"data": [
        {
            "lat": 65.56,
            "lon": 56.56,
            "dateTime": "2020-06-10 10:42:19.3200000",
            "user": {
                "id": 1,
                "username": "Viktor",
                "phone": "111"
            },
            "isGpsEnable": 0,
            "isNetworkEnable": 0
        },
        {
            "lat": 65.56,
            "lon": 56.56,
            "dateTime": "2020-06-10 10:42:35.8000000",
            "user": {
                "id": 1,
                "username": "Viktor",
                "phone": "111"
            },
            "isGpsEnable": 0,
            "isNetworkEnable": 0
        },
        {
            "lat": 65.56,
            "lon": 56.56,
            "dateTime": "2020-06-10 10:43:16.3770000",
            "user": {
                "id": 1,
                "username": "Viktor",
                "phone": "111"
            },
            "isGpsEnable": 0,
            "isNetworkEnable": 0
        },
        {
            "lat": 65.56,
            "lon": 56.56,
            "dateTime": "2020-06-10 10:45:22.4430000",
            "user": {
                "id": 1,
                "username": "Viktor",
                "phone": "111"
            },
            "isGpsEnable": 0,
            "isNetworkEnable": 0
        },
        {
            "lat": 56.8586421,
            "lon": 60.5508243,
            "dateTime": "2020-06-10 14:06:28.2400000",
            "user": {
                "id": 3,
                "username": "Вега",
                "phone": "222"
            },
            "isGpsEnable": 1,
            "isNetworkEnable": 1
        },
        {
            "lat": 56.8586421,
            "lon": 60.5508243,
            "dateTime": "2020-06-10 14:06:35.6000000",
            "user": {
                "id": 3,
                "username": "Вега",
                "phone": "222"
            },
            "isGpsEnable": 1,
            "isNetworkEnable": 1
        }
    ]
}

Т.е. фигурируют 2 юзера: Вега и Viktor. Их число может быть разным, от 1го до N.
Мне нужно неизвестным мне способом :) распарсить данные так, что бы "нарисовать" таблицу, в которую засунуть всех пользователей с их данными, а координаты этих пользователей выкинуть на карту. То-есть как на карту добавлять координаты я знаю, мне нужна помощь со структурированием данных. То-есть нужно получить видимо 2 каких-то структуры типа массивов, которые между собой как-то связаны ? Или как лучше это сделать ?
Надеюсь суть донес и задача понятна :)

laimas 13.06.2020 14:42

А можно узнать как на сервере получаются эти данные и почему эти два пользователя в ответе имеют кучу дубликатов?

lolka84 13.06.2020 16:57

Сервер работает на spring'e, почему именно так выплевывает я не знаю :(

lolka84 13.06.2020 16:59

Еще вопрос:
Сделал массив:
0: {id: 1, username: "Viktor", phone: "9221307231"}
1: {id: 1, username: "Viktor", phone: "9221307231"}
2: {id: 1, username: "Viktor", phone: "9221307231"}
3: {id: 1, username: "Viktor", phone: "9221307231"}
4: {id: 3, username: "Вега", phone: "9221307233"}
5: {id: 3, username: "Вега", phone: "9221307233"}


Сделал функцию:
function inArray(array, name) {
    $.each(array, function(i, e) {
 
        if(e.username == name) {
            return true;
        }
 
    });
 
    return false;
}


Почему console.log(inArray(usersArray, "Viktor")); всегда возвращает false ? Вставлял в блок if вывод console.log - в этот блок функция входит, но return true; почему-то функцию не останавливает.
Что я не так делаю ?

laimas 13.06.2020 17:13

Цитата:

Сообщение от lolka84
Сделал массив:

Вообще сервер уже должен отдавать:

"data": [
        {
            "lat": 65.56,
            "lon": 56.56,
            "dateTime": "2020-06-10 10:42:19.3200000",
            "user": {
                "id": 1,
                "username": "Viktor",
                "phone": "111"
            },
            "isGpsEnable": 0,
            "isNetworkEnable": 0
        },
        {
            "lat": 56.8586421,
            "lon": 60.5508243,
            "dateTime": "2020-06-10 14:06:35.6000000",
            "user": {
                "id": 3,
                "username": "Вега",
                "phone": "222"
            },
            "isGpsEnable": 1,
            "isNetworkEnable": 1
        }
    ];


и все, без дубликатов, и никаких преобразований в промежуточный объект для получения из него данных не требуется. А в том, что он у вас возвращает нужно проверять, выбирали уже такое или нет нет, так как у вас данные о "Viktor" повторяются четыре раза, а о "Вега" дважды. Это вообще на какой-то бред похоже.

lolka84 13.06.2020 17:48

Это тестовые данные, в реальных условиях конечно же одинаковых координат не будет :)
Но то, что у каждого пользователя будет именно пачка координат - от этого никуда не деться.
По функции подскажите все-таки, почему она все время false ?

laimas 13.06.2020 17:49

То есть, возьмем так. У вас "data", это свойство некоего объекта, а в примере оно как массив объектов под переменной data. Если из такого объекта нужно получить уникальные данные, а не запросом по известному, то нужно до цикла объявить переменную, которая будет хранить уникальный признак (id). В цикле ее значение проверяется со значением этого же свойства из данных и если не равны, то вывод и сохранение его в переменной.

var data = [
        {
            "lat": 65.56,
            "lon": 56.56,
            "dateTime": "2020-06-10 10:42:19.3200000",
            "user": {
                "id": 1,
                "username": "Viktor",
                "phone": "111"
            },
            "isGpsEnable": 0,
            "isNetworkEnable": 0
        },
        {
            "lat": 65.56,
            "lon": 56.56,
            "dateTime": "2020-06-10 10:42:35.8000000",
            "user": {
                "id": 1,
                "username": "Viktor",
                "phone": "111"
            },
            "isGpsEnable": 0,
            "isNetworkEnable": 0
        },
        {
            "lat": 65.56,
            "lon": 56.56,
            "dateTime": "2020-06-10 10:43:16.3770000",
            "user": {
                "id": 1,
                "username": "Viktor",
                "phone": "111"
            },
            "isGpsEnable": 0,
            "isNetworkEnable": 0
        },
        {
            "lat": 65.56,
            "lon": 56.56,
            "dateTime": "2020-06-10 10:45:22.4430000",
            "user": {
                "id": 1,
                "username": "Viktor",
                "phone": "111"
            },
            "isGpsEnable": 0,
            "isNetworkEnable": 0
        },
        {
            "lat": 56.8586421,
            "lon": 60.5508243,
            "dateTime": "2020-06-10 14:06:28.2400000",
            "user": {
                "id": 3,
                "username": "Вега",
                "phone": "222"
            },
            "isGpsEnable": 1,
            "isNetworkEnable": 1
        },
        {
            "lat": 56.8586421,
            "lon": 60.5508243,
            "dateTime": "2020-06-10 14:06:35.6000000",
            "user": {
                "id": 3,
                "username": "Вега",
                "phone": "222"
            },
            "isGpsEnable": 1,
            "isNetworkEnable": 1
        }
    ];


var id = 0;

data.forEach( (d) => {
    if(id != d.user.id) {
        id = d.user.id;
        console.log(
            'Name: ' + d.user.username +
            ', Phone: ' + d.user.phone +
            ', Latitude: ' + d.lat +
            ', Longitude: ' + d.lon +
            ', Time: ' + Date.parse(d.dateTime) + ' or ' + d.dateTime.match(/.+(?=\.)/)
        )
    }    
});


В примере вывод в консоль.

lolka84 13.06.2020 17:56

Да, я примерно так и сделал :)

var usersArray = [];
            var username;

            $.each(data.data, function(index, e) {

                if(username != e.user.username) {
                    username = e.user.username;
                
                    usersArray.push(
                        e.user
                    );

                }
                
            });

laimas 13.06.2020 18:04

Цитата:

Сообщение от lolka84
я примерно так и сделал

Строго говоря, так, это не верно. Что вы пытаетесь в таких данных найти? У вас данные, строго говоря "бракованные", они имеют дубликаты. А имя e.user.username никак не может служить гарантией уникальности (если только речь не о логинах, уникальность которых забота сервера), а значит в usersArray опять попадут дубликаты. Уникальное значение, которое обеспечивается базой, это id, его и нужно сравнивать.

lolka84 13.06.2020 18:15

Согласен, уже понял это.

laimas 13.06.2020 18:32

Цитата:

Сообщение от lolka84
Согласен, уже понял это.

Хорошо, если так. Я ведь не настаиваю, я просто сужу по данным от сервера. А сервер, судя по ним, получает данные из MySQL причем версии ниже 5.6. Это я сужу по "2020-06-10 14:06:35.6000000", так как такое может вернуть поле типа TIMESTAMP со значением по умолчанию CURRENT_TIMESTAMP (текущая дата/время как метка времени), поэтому и .6000000 в конце, и только этот тип может иметь такое значение по умолчанию. Зачем в таком формате сервер возвращает я не знаю, можно было бы и вернуть как метку времени (в примере это делает клиент) или удобочитаемую дату/время. А в версии MySQL 5.6 и выше такое значение по умолчанию может иметь и поле типа DATETIME, этот тип отличается от TIMESTAMP, он не зависит от часового пояса и в базе будет храниться как "2020-06-10 14:06:35".

В MySQL по умолчанию так же нет разницы в каком регистре что написано, можно что-то искать в одном регистре и получить два одинаковых значения в разных. Такой же финт можно сотворить и при выводе, и в итоге у вас могут появится дубликаты. А вот id значение в базе формируются полем с автоикрементом, ранее использованные значения никогда не используются и данные этого поля служат гарантией уникальности (в пределах типа поля, то есть его размера).

А если судить по этому:

"user": {
                "id": 1,
                "username": "Viktor",
                "phone": "111"
            }


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

lolka84 13.06.2020 20:46

БД mssql :) Но не суть.
Согласен, что ответ далек от идеала, но что есть, то есть.
В общем получилось вроде все, выглядит как-то так:

function getAlarms() {
    $.ajax({
        type: "GET", 
        url: url,
        dataType: 'json',
        headers: {"Authorization": token},
        cache: false,
        success: function (data) {

            var usersArray = [];
            var locationsArray = [];
            var usersIdArray = [];

            $.each(data.data, function(index, e) {

                locationsArray.push({
                    userId: e.user.id,
                    userName: e.user.username,
                    userPhone: e.user.phone,
                    lat: e.lat,
                    lon: e.lon

                });

                if($.inArray(e.user.id, usersIdArray) == -1) {
                    
                    usersIdArray.push(e.user.id);
                    usersArray.push({
                        id: e.user.id,
                        name: e.user.username,
                        phone: e.user.phone,
                        color: getRandomColor()
                    });

                }
                
            });

            console.log(usersIdArray);
            console.log(usersArray);
            console.log(locationsArray);

            createTable(usersArray);
            showOnMap(locationsArray, usersArray);
        },
        error: function (e) {
            console.log("Error: " + e);
        }
    });
}


function showOnMap(locationsArray, usersArray) {

    var myMap = new ymaps.Map('jmap', {
        center: [56.838011, 60.597465], // ekb
        zoom: 12
    });

    $.each(locationsArray, function(i, e){
        var color = getColor(usersArray, e.userId);
        console.log(color);
        var myPlace = new ymaps.Placemark([e.lat, e.lon], {
            balloonContent: e.userName + " " + e.userPhone
        }, {
            preset: 'islands#blackCircleDotIcon',
            iconColor: color
        });

        myMap.geoObjects.add(myPlace);
    });
}


function createTable(usersArray) {
    var table = $('<table id="users"/>')
    var rows = usersArray.length;

    for (var i = 0; i < rows; i++) {
        var row = $('<tr style=background-color:' + usersArray[i].color + '/>')
    
          var cell = $('<td/>')
          cell.html(usersArray[i].id);
          row.append(cell)
          var cell = $('<td/>')
          cell.html(usersArray[i].name);
          row.append(cell)
          var cell = $('<td/>')
          cell.html(usersArray[i].phone);
          row.append(cell)
    
        table.append(row)
      }
    
    table.appendTo('#table');
}


function getColor(usersArray, userId) {
    var color;
    $.each(usersArray, function(i, e){
        
        if(e.id == userId) {
            color = e.color;
            return false;            
        }

    });
    return color; 
}


function getRandomColor() {
    var letters = '0123456789ABCDEF';
    var color = '#';
    for (var i = 0; i < 6; i++) {
      color += letters[Math.floor(Math.random() * 16)];
    }
    return color;
}



$(document).ready(function() {
    ymaps.ready(getAlarms);
});

laimas 13.06.2020 21:01

$.inArray... лишнее, ибо проверку/поиск уникального можно сразу сделать и в $.each.

Цитата:

Сообщение от lolka84
БД mssql

Это не такая большая разница, могу только сказать, что коли это часть данных объекта, значит запрос к БД с подзапросом типа JOIN, а разборкой его никто себя не утруждает, вот вы и занимаетесь на клиенте граблями.


Часовой пояс GMT +3, время: 16:30.