Ένα αντικείμενο JSON είναι, για να χρησιμοποιήσουμε ορολογία από άλλες γλώσσες, ένα "hash", "map" ή "dictionary".
Το JSON ορίζει ένα αντικείμενο ως εξής:
Ένα αντικείμενο είναι ένα μη διατεταγμένο σύνολο ζευγών ονόματος/τιμής. Ένα αντικείμενο αρχίζει με
{αριστερό άγκιστρο και τελειώνει με}δεξί άγκιστρο. Κάθε όνομα ακολουθείται από:άνω και κάτω τελεία και τα ζεύγη ονόματος/τιμής χωρίζονται με,κόμμα.
Το όνομα πρέπει να είναι συμβολοσειρά. Μια άλλη λέξη για το όνομα είναι το κλειδί.
Η τιμή μπορεί να είναι οποιουδήποτε τύπου JSON. Διαφορετικές τιμές στο ίδιο αντικείμενο μπορούν να είναι διαφορετικών τύπων, όπως σε αυτό το παράδειγμα.
{
"name": "Jane",
"age": 42,
"pets": ["cat", "fish"],
"address": {"street": "123 Main St", "city": "Springfield"}
}
Σημείωσε ότι δεν πρέπει να υπάρχει κόμμα μετά το τελευταίο ζεύγος κλειδιού-τιμής.
Χρησιμοποίησε άγκιστρα για να συγκεντρώσεις τα ζεύγη ονόματος/τιμής. Αν και τα ονόματα πρέπει να είναι συμβολοσειρές, δεν χρειάζεται να περικλείονται σε εισαγωγικά αν μοιάζουν με αναγνωριστικά (αποτελούνται από αλφαριθμητικούς χαρακτήρες και κάτω παύλα, και δεν ξεκινούν με ψηφίο).
{name: "Jane", age: 42}
Είναι έγκυρο να χρησιμοποιείς κλειδιά που δεν μοιάζουν με αναγνωριστικά. Απλώς περικλείσέ τα σε εισαγωγικά.
{"first name": "Jane", "last name": "Lopez", age: 42}
Αν το όνομα είναι το αποτέλεσμα μιας έκφρασης, η έκφραση πρέπει να είναι μέσα σε παρενθέσεις.
$ echo "Jane" | jq -Rc '{.: 42}'
jq: error: syntax error, unexpected '.' (Unix shell quoting issues?) at <top-level>, line 1:
{.: 42}
jq: error: May need parentheses around object key expression at <top-level>, line 1:
{.: 42}
jq: 2 compile errors
$ echo "Jane" | jq -Rc '{(.): 42}'
{"Jane":42}
Δύο συχνές περιπτώσεις για τη δημιουργία αντικειμένων έχουν σύντομη σύνταξη.
Επαναχρησιμοποίηση ζευγών κλειδιού-τιμής από ένα αντικείμενο εισόδου.
$ jq -n '$ENV | {USER: .USER, EDITOR: .EDITOR}'
{
"USER": "glennj",
"EDITOR": "vim"
}
Το $ENV είναι ένα αντικείμενο που περιέχει τα ζεύγη ονόματος-τιμής του περιβάλλοντος.
Τα επαναλαμβανόμενα ζεύγη key: .key μπορούν να γραφτούν απλώς ως key
$ jq -n '$ENV | {USER, EDITOR}'
{
"USER": "glennj",
"EDITOR": "vim"
}
Ομοίως, υπάρχει μια συντομογραφία όταν χρησιμοποιείς μεταβλητές.
$ jq -cn '"foo" as $a | "bar" as $b | {a: $a, b: $b}'
{"a":"foo","b":"bar"}
$ jq -cn '"foo" as $a | "bar" as $b | {$a, $b}'
{"a":"foo","b":"bar"}
Οι τιμές ανακτώνται από ένα αντικείμενο με σημειογραφία τελείας.
{name: "Jane", age: 42} | .age # => 42
Αν δεν μπορείς να αναφερθείς στο κλειδί ως αναγνωριστικό, χρησιμοποίησε σημειογραφία αγκύλης.
"name" as $key | {name: "Jane", age: 42} | .$key # => error
"name" as $key | {name: "Jane", age: 42} | .[$key] # => "Jane"
Αν το κλειδί δεν υπάρχει στο αντικείμενο, το αποτέλεσμα είναι null.
{name: "Jane", age: 42} | .sport # => null
Θα ανακαλύψεις ότι αυτή είναι μια ενέργεια που χρειάζεται να κάνεις ξανά και ξανά όταν αναλύεις αποτελέσματα από ερωτήματα API.
Δεδομένου ενός αντικειμένου που περιέχει τιμές πίνακα ή αντικειμένου, μπορούμε να "αλυσιδώσουμε" μεταξύ τους εκφράσεις ευρετηρίασης.
{
"name": "Jane",
"age": 42,
"pets": ["cat", "fish"],
"address": {"street": "123 Main St", "city": "Springfield"}
}
| (
.pets[1], # => "fish"
.address.city # => "Springfield"
)
Για να προσθέσεις ένα νέο ζεύγος κλειδιού-τιμής σε έναν πίνακα, ή για να ενημερώσεις την τιμή ενός υπάρχοντος κλειδιού, χρησιμοποίησε τον τελεστή ανάθεσης =, με μια έκφραση ευρετηρίασης στην αριστερή πλευρά.
{name: "Jane", age: 42} | .sport = "tennis" | .age = 21
# => {
# "name": "Jane",
# "age": 21,
# "sport": "tennis"
# }
Ο τελεστής + θα συγχωνεύσει τα αντικείμενα.
{Richard: 54} + {Jane: 42}
# => {
# "Richard": 54,
# "Jane": 42
# }
Χρησιμοποίησε τη συνάρτηση del για να αφαιρέσεις ένα κλειδί.
Επιστρέφει το ενημερωμένο αντικείμενο.
{name: "Jane", age: 42} | del(.age) # => {"name": "Jane"}
Η παράμετρος της del είναι μια έκφραση ευρετηρίασης (με σημειογραφία τελείας ή αγκύλης) που καταλήγει σε ένα κλειδί του αντικειμένου.
Το jq την ονομάζει έκφραση διαδρομής.
Δεν αρκεί να δώσεις απλώς μια συμβολοσειρά.
{name: "Jane", age: 42} | del(name) # error: name/0 is not defined
{name: "Jane", age: 42} | del("name") # error: Invalid path expression with result "name"
{name: "Jane", age: 42} | del(.name) # OK
{name: "Jane", age: 42} | del(.["name"]) # OK
Για να ελέγξεις αν το αντικείμενο έχει ένα κλειδί, χρησιμοποίησε τη συνάρτηση has.
{name: "Jane", age: 42} as $example
|
($example | has("name")), # => true
($example | has("sport")) # => false
Έλεγξε αν ένα κλειδί βρίσκεται σε ένα αντικείμενο με το in.
{name: "Jane", age: 42} as $example
|
("name" | in($example)), # => true
("sport" | in($example)) # => false
Χρησιμοποίησε τη συνάρτηση keys για να εμφανίσεις μια λίστα με όλα τα κλειδιά.
{name: "Jane", age: 42} | keys # => ["age", "name"]
Σημείωσε ότι η keys θα ταξινομήσει τα κλειδιά.
Για να ανακτήσεις τα κλειδιά με την αρχική σειρά, χρησιμοποίησε τη keys_unsorted.
Δεν υπάρχει αντίστοιχη συνάρτηση για να καταγράψεις όλες τις τιμές.
Ωστόσο το φίλτρο .[] εμφανίζει τις τιμές του αντικειμένου ως ροή, και αυτή η ροή μπορεί να συλλεχθεί με τον κατασκευαστή πίνακα [...].
[{first: "Jane", last: "Lopez", status: "awesome!"} | .[]]
# => ["Jane", "Lopez", "awesome!"]
Η συνάρτηση map_values(filter) εφαρμόζει το φίλτρο σε κάθε τιμή του αντικειμένου.
{first: "Jane", last: "Lopez", status: "awesome!"}
| map_values(ascii_upcase)
# => {"first": "JANE", "last": "LOPEZ", "status": "AWESOME!"}
Για να επαναλάβουμε πάνω σε ένα αντικείμενο, πρέπει πρώτα να το μετατρέψουμε σε έναν πίνακα από αντικείμενα κλειδιού-τιμής.
Η συνάρτηση to_entries το κάνει αυτό.
{name: "Jane", age: 42} | to_entries
# => [
# {
# "key": "name",
# "value": "Jane"
# },
# {
# "key": "age",
# "value": 42
# }
# ]
Σε αυτό το σημείο, μπορούμε να χρησιμοποιήσουμε συναρτήσεις επανάληψης πινάκων, όπως τη map.
Η συνάρτηση from_entries είναι η αντίστροφη: μετατρέπει έναν πίνακα από αντικείμενα κλειδιού-τιμής σε ένα αντικείμενο.
[
{"key":"name", "value":"Jane"},
{"key":"age", "value":42}
] | from_entries # => {"name": "Jane", "age": 42}
Για να εφαρμόσεις ένα φίλτρο σε κάθε ζεύγος κλειδιού-τιμής ενός αντικειμένου, χρησιμοποίησε τη συνάρτηση with_entries(filter).
Για παράδειγμα, δεδομένου ενός αντικειμένου που αντιστοιχίζει ένα όνομα σε μια ηλικία, τα κλειδιά και οι τιμές μπορούν να ανταλλαγούν ως εξής.
{"Jane": 42, "Richard": 54}
| with_entries({key: (.value | tostring), value: .key})
παράγει
{
"42": "Jane",
"54": "Richard"
}
Η with_entries(filter) είναι το ίδιο με
to_entries | map(filter) | from_entries