• Najnowsze pytania
  • Bez odpowiedzi
  • Zadaj pytanie
  • Kategorie
  • Tagi
  • Zdobyte punkty
  • Ekipa ninja
  • IRC
  • FAQ
  • Regulamin
  • Książki warte uwagi

Parsowanie danych JSON w JS na potrzeby wykresów Highcharts

Mały hosting, OGROMNE możliwości
+2 głosów
1,487 wizyt
pytanie zadane 4 stycznia 2017 w JavaScript przez avrfun Nowicjusz (140 p.)

Witam. Próbuję zmierzyć się z wykresami Highcharts tworzonymi z plików JSON. Mam problem z "przekodowaniem" danych JSON na format akceptowany przez wykresy. Chciałbym utworzyć wykres kolumnowy, który na osi x zawierałby kategorie (2010, 2011, 2012, 2014), a w każdej kategorii 3 serie danych (soki, dżemy, desery), których wartość prezentowana jest na osi y. Bezpośrednie wpisanie danych do serii w opcjach wykresu generuje go poprawnie. Oto kod:

<!DOCTYPE html>

<html lang="en" xmlns="http://www.w3.org/1999/xhtml">
<head>
    <meta charset="utf-8" />
    <title>Update Series Data</title>
    <script type="text/javascript" src="js/jquery-1.9.1.js"></script>
    <script type="text/javascript" src="js/highcharts.js"></script>
    <script type="text/javascript">
        $(function () {
           
		    var json = [{
			
					//name: 'Soki', data:[70, 75, 65, 90, 85]},
					//{name: 'Dżemy', data:[80, 45, 90, 85, 90]},
					//{name: 'Desery', data:[80, 80, 90, 101, 90],
			
			}];
			
			var processed_json = new Array();
			$.map(json, function(obj, i) {
				processed_json.push([obj.name, parseFloat(obj.data)]);
			});


			$('#container').highcharts({
				chart: {
					type: 'column'
				},
				xAxis: {
					//type: "category"
					categories:['2010','2011','2012','2013','2014']
					
				},
				series: [{
							//data: processed_json
							name: 'Soki', data:[70, 75, 65, 90, 85]},
							{name: 'Dżemy', data:[80, 45, 90, 85, 90]},
							{name: 'Desery', data:[80, 80, 90, 101, 90],
							
				}]
			});
		});
    </script>
</head>
<body>
    <div id="container" style="height: 300px"></div>
</body>
</html>

Po wpisaniu tych danych do zmiennej json wykres nie generuje się już poprawnie. Na osi x jest rok 2010, 2011, 2012, a do każdego roku przypisane są po kolei soki, dżemy, desery. Coś jest nie tak z parsowaniem danych. Nie mogę znaleźć przyczyny i bardzo proszę o pomoc. Kod wygląda tak:

<!DOCTYPE html>

<html lang="en" xmlns="http://www.w3.org/1999/xhtml">
<head>
    <meta charset="utf-8" />
    <title>Update Series Data</title>
    <script type="text/javascript" src="js/jquery-1.9.1.js"></script>
    <script type="text/javascript" src="js/highcharts.js"></script>
    <script type="text/javascript">
        $(function () {
           
		    var json = [{
			
					name: 'Soki', data:[70, 75, 65, 90, 85]},
					{name: 'Dżemy', data:[80, 45, 90, 85, 90]},
					{name: 'Desery', data:[80, 80, 90, 101, 90],
			
			}];
			
			var processed_json = new Array();
			$.map(json, function(obj, i) {
				processed_json.push([obj.name, parseFloat(obj.data)]);
			});


			$('#container').highcharts({
				chart: {
					type: 'column'
				},
				xAxis: {
					//type: "category"
					categories:['2010','2011','2012','2013','2014']
					
				},
				series: [{
							data: processed_json
				}]
			});
		});
    </script>
</head>
<body>
    <div id="container" style="height: 300px"></div>
</body>
</html>

Pozdrawiam

avrfun

komentarz 4 stycznia 2017 przez ScriptyChris Mędrzec (190,190 p.)

Wydaje mi się, że błędnie utworzyłeś JSONa, rozumianego jako format wymiany danych. W JSONie klucze muszą być objęte cudzysłowami - u Ciebie nie są. Wg MDN

Property names must be double-quoted strings; trailing commas are forbidden.

+

strings must be double-quoted

Wrzuć sobie zawartość zmiennej json do walidatora, np. https://jsonformatter.curiousconcept.com/ i przekonasz się sam.

Proponuję najpierw serializować zmienną json do "prawdziwego" JSONa, czyli:

$.map(  JSON.stringify( json ), function(obj, i) {
        processed_json.push([obj.name, parseFloat(obj.data)]);
 });
komentarz 4 stycznia 2017 przez avrfun Nowicjusz (140 p.)

Bardzo dziękuję za odpowiedź i zwrócenie uwagi na błędy. Poprawiłem plik JSON i teraz przechodzi on walidację na stronie którą mi podałeś"

var json = [
			{
			"name": "Soki",
			"data": [70, 75, 65, 90, 85]
			},
			{
			"name": "Dżemy",
			"data": [80, 45, 90, 85, 90]
			},
			{
			"name":"Desery",
			"data": [60, 80, 90, 101, 90]
			}
		   ]

Po tej zmianie niestety nadal na wykresie pojawia się jedna seria danych. Dane mam serializowane jak poniżej:

var processed_json = new Array();
			
			$.map(json, function(obj, i) {
			processed_json.push([obj.name, parseFloat(obj.data)]);
			});

Zmiana json na JSON.stringify(json) w argumencie funkcji $.map sprawia, że wykres nie generuje się.

komentarz 4 stycznia 2017 przez ScriptyChris Mędrzec (190,190 p.)

Czy konsola wyrzuca jakieś błędy?

Tak w ogóle, to metoda dla tablic .map() zwraca Tobie nową tablicę, więc jeśli korzystasz z push() to wystarczy Ci .forEach() - bo nic nie zwracasz. Jeśli chcesz nową tablicę, to zastosuj .map() i zwracaj [obj.name, parseFloat(obj.data)]. Poza tym, czy nie za bardzo zagnieżdżasz te tablicę? Wykonujesz push(), którym do tablicy wrzucasz tablicę z danymi, zamiast po prostu - wrzucać dane. Domyślam się, że Highcharts tworzy wykresy w oparciu o m.in parametr którym jest tablica - jeśli nie, to może nie twórz takich zagnieżdżeń?

Popatrz (wyciąłem kawałki z Twojego kodu):

var processed_json = new Array();
$.map(json, function(obj, i) {
     processed_json.push([obj.name, parseFloat(obj.data)]);
 });

....

series: [{
       data: processed_json
}]

Zmienna processed_json jest tablicą, w której umieściłeś tablicę z elementami: obj.name, parseFloat(obj.data). Czyli już masz tablicę tablic. Następnie tworzysz wykres posyłając w obiekcie pole series, które zawiera tablicę, a jej pierwszym elementem jest obiekt z polem data, który zawiera wspomnianą tablicę tablic. Czy jesteś pewny, że struktura danych do tworzenia wykresu przez tą bibliotekę powinna posiadać taki poziom zagnieżdżenia?

Sprawdź konsolę i jeszcze raz przeanalizuj jakie parametry są potrzebne do tworzenia wykresu.

komentarz 4 stycznia 2017 przez avrfun Nowicjusz (140 p.)
edycja 4 stycznia 2017 przez avrfun

Zobacz proszę jak wygląda format danych chart dla wykresów Highcharts. Dane zgromadzone są w opcjach wykresu. Chcę zrobić dokładnie taki sam wykres, ale z danymi JSON, które będą generowane przez skrypt php.

http://jsfiddle.net/gh/get/jquery/3.1.1/highslide-software/highcharts.com/tree/master/samples/highcharts/demo/column-basic/

Format pliku JSON dla wykresu ma wyglądać tak:

[
[1,12],
[2,5],
[3,18],
[4,13],
[5,7],
[6,4],
[7,9],
[8,10],
[9,15],
[10,22]
]

Tablica tablic rozumiem, na dole strony z linku poniżej:

PREPROCESS DATA USING JSON:

http://www.highcharts.com/docs/working-with-data/custom-preprocessing

Zmieniełem zapis w polu series na:

series: processed_json

Wyświetla się, legenda zawierająca 3 serie, ale wykresu brak.

 

1
komentarz 4 stycznia 2017 przez ScriptyChris Mędrzec (190,190 p.)

Hmm, czyż Twoja tablica json nie jest już tym co powinno być w series?

W podlinkowanym przez Ciebie JSFiddle series zawiera:

series: [{
            name: 'Tokyo',
            data: [49.9, 71.5, 106.4, 129.2, 144.0, 176.0, 135.6, 148.5, 216.4, 194.1, 95.6, 54.4]
     }
....
];

Czyli struktura taka jak Twoja zmienna json (pole name zawiera string z nazwą miasta, a pole data tablicę z liczbami). Zapisz zatem po prostu:

 series: json

 

komentarz 4 stycznia 2017 przez avrfun Nowicjusz (140 p.)
edycja 5 stycznia 2017 przez avrfun

Bardzo dziękuję - genialne - działa. Patrzyłem i nie widziałem. Mapowanie jest więc zbędne. Napisz gdzie kliknąć "bardzo pomógł" bo jestem nowy na Forum. Mam jeszcze jedno pytanie jeżeli nie nadużyję Twojej cierpliwości?

Dane realne ze stacji meteo w pliku JSON - tutaj chyba bez parsowania danych, a przynajmniej czasu się

<!DOCTYPE html>

<html lang="en" xmlns="http://www.w3.org/1999/xhtml">
<head>
    <meta charset="utf-8" />
    <title>Update Series Data</title>
    <script type="text/javascript" src="js/jquery-1.9.1.js"></script>
    <script type="text/javascript" src="js/highcharts.js"></script>
    <script type="text/javascript">
        $(function () {
           
			 var json = [  
						   {  
							  "czas_datetime":"2017-01-03 23:25:00",
							  "wind_direction_average":"227.7",
							  "wind_speed_average":"11.45",
							  "windgust":"23.62",
							  "compass":"SW"
						   },
						   {  
							  "czas_datetime":"2017-01-03 23:26:00",
							  "wind_direction_average":"227.6",
							  "wind_speed_average":"9.44",
							  "windgust":"19.96",
							  "compass":"SW"
						   },
						   {  
							  "czas_datetime":"2017-01-03 23:27:00",
							  "wind_direction_average":"227.4",
							  "wind_speed_average":"13.09",
							  "windgust":"29.08",
							  "compass":"SW"
						   }
						]


			
			var processed_json = new Array();
			$.map(json, function(obj, i) {
			processed_json.push([obj.czas_datetime, parseFloat(obj.wind_speed_average)]);
			});
			
			//$.map(JSON.stringify(json), function(obj, i) {
        	//processed_json.push([obj.name, parseFloat(obj.data)]);
 			//});


			$('#container').highcharts({
				chart: {
					type: 'column'
				},
				xAxis: {
					type: "category"
					
				},

					series: json
			});
		});
    </script>
</head>
<body>
    <div id="container" style="height: 300px"></div>
</body>
</html>

nie obejdzie:

Aktualnie wykres z danymi ze stacji meteo ma jedną serię danych (wind_speed_average) i nie mogę uzyskać drugiej (wind_gust):

<!DOCTYPE html>

<html lang="en" xmlns="http://www.w3.org/1999/xhtml">
<head>
    <meta charset="utf-8" />
    <title>Update Series Data</title>
    <script type="text/javascript" src="js/jquery-1.9.1.js"></script>
    <script type="text/javascript" src="js/highcharts.js"></script>
    <script type="text/javascript">
        $(function () {
           
		    var json = [
							{  
							  "czas_datetime":"2017-01-01 20:02:00",
							  "wind_direction_average":"231.4",
							  "wind_speed_average":"6.71",
							  "windgust":"13.43",
							  "compass":"SW"
						   },
						   {  
							  "czas_datetime":"2017-01-01 20:03:00",
							  "wind_direction_average":"232.7",
							  "wind_speed_average":"6.62",
							  "windgust":"13.26",
							  "compass":"SW"
						   },
						   {  
							  "czas_datetime":"2017-01-01 20:04:00",
							  "wind_direction_average":"233.7",
							  "wind_speed_average":"5.50",
							  "windgust":"17.07",
							  "compass":"SW"
						   },
						   {  
							  "czas_datetime":"2017-01-01 20:05:00",
							  "wind_direction_average":"242.8",
							  "wind_speed_average":"6.35",
							  "windgust":"15.62",
							  "compass":"WSW"
						   },
						   {  
							  "czas_datetime":"2017-01-01 20:06:00",
							  "wind_direction_average":"233.7",
							  "wind_speed_average":"4.50",
							  "windgust":"19.52",
							  "compass":"SW"
						   },
						   {  
							  "czas_datetime":"2017-01-01 20:07:00",
							  "wind_direction_average":"229.7",
							  "wind_speed_average":"6.54",
							  "windgust":"17.71",
							  "compass":"SW"
						   },
						   {  
							  "czas_datetime":"2017-01-01 20:08:00",
							  "wind_direction_average":"229.0",
							  "wind_speed_average":"3.26",
							  "windgust":"8.81",
							  "compass":"SW"
						   }
					]
			
			var processed_json = new Array();
			$.map(json, function(obj, i) {
				processed_json.push([obj.czas_datetime, parseFloat(obj.wind_speed_average), parseFloat(obj.windgust)]);
			});


			$('#container').highcharts({
				chart: {
					type: 'line'
				},
				xAxis: {
					type: "category"
					//categories:['2010','2011','2012','2013','2014']
					
				},
				series: [
							{
								data: processed_json
							}
						]
				});
		});
    </script>
</head>
<body>
    <div id="container" style="height: 300px"></div>
</body>
</html>

 

komentarz 5 stycznia 2017 przez ScriptyChris Mędrzec (190,190 p.)

Napisz gdzie kliknąć "bardzo pomógł" bo jestem nowy na Forum

Nie ma możliwości wybrania komentarza jako najlepszą odpowiedź (czy też najbardziej pomocna), możesz jedynie kliknąć w lewym górnym rogu komentarza na strzałeczkę w górę - określisz że była po prostu pomocna/spodobała Ci się.

Aktualnie wykres z danymi ze stacji meteo ma jedną serię danych (wind_speed_average) i nie mogę uzyskać drugiej (wind_gust):

Znowu nie przypisałeś tablicy json do pola series - chyba, że wstawiłeś nieaktualny kod? 

komentarz 6 stycznia 2017 przez avrfun Nowicjusz (140 p.)
edycja 6 stycznia 2017 przez avrfun

Przypisanie zmiennej json do pola series w przykładzie z ostatniego mojego postu sprawia, że wykres nie generuje się wcale. Pojawia się tylko legenda zawierająca 7 serii danych, a więc tyle ile jest "grup" danych JSON. Poprzednio zadziałało bo każda seria miała swoją nazwę w pierwszej linii danych JSON np. soki, dżemy, deser"

{
	"name": "Soki",
	"data": [70, 75, 65, 90, 85]
},
{
    "name": "Dżemy",
    "data": [80, 45, 90, 85, 90]
},
{
    "name":"Desery",
    "data": [60, 80, 90, 101, 90]
}

Teraz jest inaczej. Pierwsza linia danych zawiera nie serie danych tylko czas, który powinien być obrazowany na osi x w postaci godzin (00-23). Serie zaczynają się od drugiej linii danych: wind_direction_average, wind_speed_average, windgust, compass np.:

{  
    "czas_datetime":"2017-01-01 20:02:00",
    "wind_direction_average":"231.4",
    "wind_speed_average":"6.71",
    "windgust":"13.43",
    "compass":"SW"
 }

Wydaje mi się, że czas należy sparsować i zaprezentować go (tylko godziny) na osi x, a w tooltipie dla każdej danej będzie widoczny wówczas pełny czas, którego ona dotyczy.

W opcjach wykresu zaznaczamy wówczas kategorię osi x jako datatime:

xAxis: {
		type: "datetime"
	    },

Pozdrawiam.

Zaloguj lub zarejestruj się, aby odpowiedzieć na to pytanie.

Podobne pytania

0 głosów
2 odpowiedzi 1,127 wizyt
+1 głos
2 odpowiedzi 2,470 wizyt
pytanie zadane 8 września 2020 w JavaScript przez Marak123 Stary wyjadacz (11,190 p.)
0 głosów
1 odpowiedź 710 wizyt

93,715 zapytań

142,629 odpowiedzi

323,259 komentarzy

63,255 pasjonatów

Motyw:

Akcja Pajacyk

Pajacyk od wielu lat dożywia dzieci. Pomóż klikając w zielony brzuszek na stronie. Dziękujemy! ♡

Oto polecana książka warta uwagi.
Pełną listę książek znajdziesz tutaj

Twierdza Linux. Bezpieczeństwo dla dociekliwych

Aby uzyskać rabat -10%, użyjcie kodu pasja-linux, wpisując go w specjalne pole w koszyku.

...