The Perl Toolchain Summit 2025 Needs You: You can help 🙏 Learn more

NAME

Quiq::Json::Code - Erzeuge JSON-Code in Perl

BASE CLASS

Quiq::Hash

SYNOPSIS

Klasse laden und Objekt instantiieren

my $j = Quiq::Json::Code->new;

JSON-Objekt via object()

$json = $j->object(
pi => 3.14159,
str => 'Hello world!',
bool => \'true',
obj => $j->object(
id => 4711,
name => 'Wall',
numbers => [1..5],
),
min => undef,
);

erzeugt

{
pi: 3.14159,
str: 'Hello world!',
bool: true,
obj: {
id: 4711,
name: 'Wall',
numbers: [1,2,3,4,5],
},
min: undefined,
}

Bei der Methode $j->object()

  • bleibt die Reihenfolge der Schlüssel/Wert-Paare erhalten

  • jedes Schlüssel/Wert-Paar beginnt auf einer eigenen Zeile und wird eingerückt

JSON-Datenstruktur via encode()

$json = $j->encode({
pi => 3.14159,
str => 'Hello world!',
bool => \'true',
obj => {
id => 4711,
name => 'Wall',
numbers => [1..5],
},
min => undef,
});

erzeugt

{bool:true,min:undefined,obj:{id:4711,name:'Wall',numbers:[1,2,3,4,5]},pi:3.14159,str:'Hello world!'}

Bei der Methode $j->encode()

  • werden die Schlüssel/Wert-Paare von JSON-Objekten alphanumerisch sortiert (bei {...} ist die Reihenfolge sonst undefiniert)

  • gibt es keine Einrückung oder Leerraum nach dem :

DESCRIPTION

Die Klasse ermöglicht die präzise Erzeugung von JavaScript-Datenstrukturen aus Perl heraus. Der Fokus liegt nicht auf der Übermittlung von Daten, sondern auf der Einsetzung der Strukturen in JavaScript-Quelltexte. Insofern gehen die Möglichketen der Klasse über JSON hinaus. Die JavaScript-Klasse Chart.js arbeitet z.B. mit einer komplexen Datenstruktur. Diese Struktur aus Perl heraus dynamisch erzeugen zu können, war der Anlass für die Entwicklung dieser Klasse. Das Perl-Modul JSON ist für diese Zwecke nicht geeignet, denn z.B. kann eine JavaScript-Datenstruktur Referenzen auf (inline definierte) JavaScript-Funktionen enthalten. Dies ist mit dieser Klasse möglich. Weitere Vorteile dieser Klasse:

  • die Reihenfolge von Objektattributen bleibt erhalten

  • Werte können literal eingesetzt werden (z.B. Funktionsdefinionen, spezielle Werte wie true, false, null usw.)

  • lesbarerer Code

EXAMPLE

Ein realer Fall. Die Erzeugung einer Konfiguration für Chart.js. Wir nutzen hier die Aliase o() und c() für die Methoden object() und code().

my @dataSets;
my $title = 'Windspeed';
my $unit = 'm/s';
my $tMin = undef;
my $tMax = undef;
my $yMin = 0;
my $yMax = undef;
$json = $j->o(
type => 'line',
data => $j->o(
datasets => \@dataSets,
),
options => $j->o(
maintainAspectRatio => \'false',
title => $j->o(
display => \'true',
text => $title,
fontSize => 16,
fontStyle => 'normal',
),
tooltips => $j->o(
intersect => \'false',
displayColors => \'false',
backgroundColor => 'rgb(0,0,0,0.6)',
titleMarginBottom => 2,
callbacks => $j->o(
label => $j->c(qq~
function(tooltipItem,data) {
var i = tooltipItem.datasetIndex;
var label = data.datasets[i].label || '';
if (label)
label += ': ';
label += tooltipItem.value + ' $unit';
return label;
}
~),
),
),
legend => $j->o(
display => \'false',
),
scales => $j->o(
xAxes => [$j->o(
type => 'time',
ticks => $j->o(
minRotation => 30,
maxRotation => 60,
),
time => $j->o(
min => $tMin,
max => $tMax,
minUnit => 'second',
displayFormats => $j->o(
second => 'YYYY-MM-DD HH:mm:ss',
minute => 'YYYY-MM-DD HH:mm',
hour => 'YYYY-MM-DD HH',
day => 'YYYY-MM-DD',
week => 'YYYY-MM-DD',
month => 'YYYY-MM',
quarter => 'YYYY [Q]Q',
year => 'YYYY',
),
tooltipFormat => 'YYYY-MM-DD HH:mm:ss',
),
)],
yAxes => [$j->o(
ticks => $j->o(
min => $yMin,
max => $yMax,
),
scaleLabel => $j->o(
display => \'true',
labelString => $unit,
),
)],
),
),
);

erzeugt

{
type: 'line',
data: {
datasets: [],
},
options: {
maintainAspectRatio: false,
title: {
display: true,
text: 'Windspeed',
fontSize: 16,
fontStyle: 'normal',
},
tooltips: {
intersect: false,
displayColors: false,
backgroundColor: 'rgb(0,0,0,0.6)',
titleMarginBottom: 2,
callbacks: {
label: function(tooltipItem,data) {
var i = tooltipItem.datasetIndex;
var label = data.datasets[i].label || '';
if (label)
label += ': ';
label += tooltipItem.value + ' m/s';
return label;
},
},
},
legend: {
display: false,
},
scales: {
xAxes: [{
type: 'time',
ticks: {
minRotation: 30,
maxRotation: 60,
},
time: {
min: undefined,
max: undefined,
minUnit: 'second',
displayFormats: {
second: 'YYYY-MM-DD HH:mm:ss',
minute: 'YYYY-MM-DD HH:mm',
hour: 'YYYY-MM-DD HH',
day: 'YYYY-MM-DD',
week: 'YYYY-MM-DD',
month: 'YYYY-MM',
quarter: 'YYYY [Q]Q',
year: 'YYYY',
},
tooltipFormat: 'YYYY-MM-DD HH:mm:ss',
},
}],
yAxes: [{
ticks: {
min: 0,
max: undefined,
},
scaleLabel: {
display: true,
labelString: 'm/s',
},
}],
},
},
}

METHODS

Instantiierung

new() - Konstruktor

Synopsis

$j = $class->new(@keyVal);

Attributes

indent => $n (Default: 4)

Tiefe der Einrückung.

Returns

Objekt

Description

Instantiiere ein Objekt der Klasse und liefere eine Referenz auf dieses Objekt zurück.

Objektmethoden

code() - Erzeuge Sourcecode für JSON-Datenstruktur

Synopsis

$code = $j->code($text); # Scalar-Kontext
($codeS) = $j->code($text); # List-Kontext

Alias

c()

Arguments

$text

Sourcecode, typischerweise mehrzeiliger JavaScript-Code.

Returns

Sourecode (String). Im List-Kontext eine Referenz auf den Code.

Description

Erzeuge Sourcecode, der in eine JSON-Datenstruktur eingebettet werden kann, und liefere diesen zurück. Der Code

  • erhält die richtige Einrückung

  • wird "as is" eingebettet, also nicht gequotet

Example

Weise Funktionsreferenz an Objekt-Attribut zu

$unit = 'm/s';
$json = $j->object(
label => $j->code(qq~
function(tooltipItem,data) {
var i = tooltipItem.datasetIndex;
var label = data.datasets[i].label || '';
if (label)
label += ': ';
label += tooltipItem.value + ' $unit';
return label;
}
~),
),

liefert

{
label: function(tooltipItem,data) {
var i = tooltipItem.datasetIndex;
var label = data.datasets[i].label || '';
if (label)
label += ': ';
label += tooltipItem.value + ' m/s';
return label;
},
}

encode() - Wandele Perl- in JavaScript-Datenstruktur

Synopsis

$json = $j->encode($scalar);

Arguments

$scalar

Skalarer Wert: undef, \0, \1, Number, String, String-Referenz, Array-Referenz, Hash-Referenz.

Returns

JSON-Code (String)

Description

Wandele $scalar nach JSON und liefere den resultierenden Code zurück. Die Übersetzung erfolgt (rekursiv) nach folgenden Regeln:

undef

Wird abgebildet auf: undefined. In einem Objekt wird das betreffende Attribut weggelassen.

\1 oder \'true'

Wird abgebildet auf: true

\0 oder \'false'

Wird abgebildet auf: false

NUMBER

Wird unverändert übernommen: NUMBER

STRING

Wird abgebildet auf: 'STRING'

STRING_REF

Wird abgebildet auf: STRING (literale Einsetzung von STRING)

Dies ist z.B. nützlich, wenn ein Teil der Datenstruktur abweichend formatiert werden soll.

ARRAY_REF

Wird abgebildet auf: [ELEMENT1,ELEMENT2,...]

HASH_REF

Wird abgebildet auf: {KEY1:VALUE1,KEY2:VALUE2,...}. Im Falle des Werts undef, wird das betreffende Schlüssel/Wert-Paar weggelassen.

object() - Erzeuge Code für JSON-Objekt

Synopsis

$json = $j->object(@opt,@keyVal); # Scalar-Kontext
($jsonS) = $j->object(@opt,@keyVal); # List-Kontext

Alias

o()

Arguments

@keyVal

Liste der Schlüssel/Wert-Paare

Options

-indent => $bool (Default: 1)

Rücke die Elemente des Hash ein.

Returns

JSON-Code (String). Im List-Kontext eine Referenz auf den Code.

Description

Erzeuge den Code für ein JSON-Objekt mit den Attribut/Wert-Paaren @keyVal und liefere diesen zurück.

Hilfsmethoden

key() - Schlüssel eines JSON-Objekts

Synopsis

$str = $j->key($key);

Arguments

$key

Schlüssel.

Returns

String

Description

Erzeuge den Code für den Schlüssel $key eines JSON-Objekts und liefere diesen zurück. Enthält der Schlüssel nur Zeichen, die in einem JavaScript-Bezeichner vorkommen dürfen, wird er unverändert geliefert, ansonsten wird er in einfache Anführungsstriche eingefasst.

Example

Schlüssel aus dem Zeichenvorrat eines JavaScript-Bezeichners:

$str = $j->Quiq::Json::Code('borderWidth');
==>
"borderWidth"

Schlüssel mit Zeichen, die nicht in einem JavaScript-Bezeichner vorkommen:

$str = $j->Quiq::Json::Code('border-width');
==>
"'border-width'"

VERSION

1.225

AUTHOR

Frank Seitz, http://fseitz.de/

COPYRIGHT

Copyright (C) 2025 Frank Seitz

LICENSE

This code is free software; you can redistribute it and/or modify it under the same terms as Perl itself.