Go 1.25 encoding/json v1 vs v2 -vertailu
Go-kielen encoding/json
-paketin v2 on uusi toteutus, joka pyrkii parantamaan useita v1:n puutteita (epäjohdonmukaisuus, yllättävä käyttäytyminen, suorituskykyongelmat). Tämä on kokeellinen ominaisuus, joka aktivoidaan goexperiment.jsonv2
-rakennustunnisteen kautta.
Tärkeintä on, että kun v2 on aktivoitu, v1 toimii yhteensopivuuskerroksena, joka emuloi v1:n käyttäytymistä v2-toteutuksen päällä. Tämä tapahtuu v2_v1.go
-tiedoston DefaultOptionsV1()
-funktion kautta. Toisin sanoen, v2 tarjoaa vaihtoehtoja, joilla v1:n käyttäytyminen voidaan toistaa täydellisesti, ja samalla se esittelee uuden, tiukemman ja ennustettavamman oletuskäyttäytymisen.
V2:n päätavoitteet ovat seuraavat:
- Tarkkuuden ja ennustettavuuden parantaminen: Soveltamalla oletuksena tiukempia sääntöjä (esim. kirjainkoon huomioiminen, päällekkäisten avainten kieltäminen) vähennetään odottamatonta käyttäytymistä.
- Suorituskyvyn parantaminen: Jäsennys- ja koodausmoottorit on suunniteltu uudelleen tehokkuuden lisäämiseksi.
- Joustavuuden ja hallinnan laajentaminen: Yksityiskohtainen Options-järjestelmä on otettu käyttöön, jotta kehittäjät voivat hallita JSON-käsittelytapaa tarkasti.
Tärkeimmät semanttiset/toiminnalliset erot
Olemme koonneet v1:n ja v2:n käyttäytymisen erot kohtakohtaisesti keskittyen v2_test.go
-tiedostoon.
1. Kentän nimen täsmäytys (kirjainkoon huomioiminen)
- v1-käyttäytyminen: Kun JSON-objektin jäseniä puretaan Go-rakenteen kenttiin, täsmäytys tapahtuu kirjainkoosta riippumatta (case-insensitive). Sekä
"FirstName"
että"firstname"
kartoitetaanFirstName
-kenttään. - v2-käyttäytyminen: Oletuksena täsmäytys tapahtuu kirjainkoon huomioiden (case-sensitive), ja vain tarkasti vastaavat kentät kartoitetaan.
- Muutoksen syy: Kirjainkoosta riippumaton täsmäytys voi aiheuttaa odottamatonta käyttäytymistä ja heikentää suorituskykyä käsiteltäessä täsmäämättömiä kenttiä. V2 on ottanut käyttöön selkeämmän ja ennustettavamman käyttäytymisen oletuksena.
- Liittyvät Options: V2:ssa voidaan käyttää
json:"...,case:ignore"
-tunnisteoptiota aktivoimaan kirjainkoosta riippumaton täsmäytys kenttäkohtaisesti tai soveltamaanjson.MatchCaseInsensitiveNames(true)
-optiota globaalisti.
2. omitempty
-tunnisteoption merkityksen muutos
- v1-käyttäytyminen: Kenttä jätetään pois Go-arvon "tyhjästä tilasta" riippuen. Tässä "tyhjä tila" tarkoittaa
false
,0
,nil
-osoitinta/rajapintaa, tai nollapituisia taulukkoja/viipaleita/mappeja/merkkijonoja. - v2-käyttäytyminen: Kenttä jätetään pois koodatun JSON-arvon "tyhjästä tilasta" riippuen. Toisin sanoen, jos se koodataan
null
,""
,{}
,[]
, se jätetään pois. - Muutoksen syy: v1:n määritelmä on riippuvainen Go:n tyyppijärjestelmästä. v2 tarjoaa johdonmukaisemman käyttäytymisen perustuen JSON-tyyppijärjestelmään. Esimerkiksi v1:ssä
bool
-tyypinfalse
-arvo jätetään pois, mutta v2:ssafalse
ei ole tyhjä JSON-arvo, joten sitä ei jätetä pois. V2:ssa on lisättyomitzero
-optio, jolla voidaan korvata v1:nomitempty
-käyttäytyminen, joka koski0
taifalse
. - Liittyvät Options: Jos v2:ssa halutaan sama käyttäytyminen kuin v1:ssä, käytetään
json.OmitEmptyWithLegacyDefinition(true)
-optiota.
3. string
-tunnisteoption käyttäytymisen muutos
- v1-käyttäytyminen: Soveltuu numero-, totuusarvo- ja merkkijonotyyppisiin kenttiin. Koodaa arvon uudelleen JSON-merkkijonon sisään (esim.
int(42)
->"42"
). Ei sovelleta rekursiivisesti yhdistelmätyyppien (viipaleet, mapit jne.) sisällä oleviin arvoihin. - v2-käyttäytyminen: Soveltuu vain numerotyyppeihin ja sovelletaan rekursiivisesti. Toisin sanoen, kaikki numerot
[]int
-tyyppisen viipaleen sisällä koodataan myös JSON-merkkijonoiksi. - Muutoksen syy:
string
-option pääasiallinen käyttötarkoitus on esittää numeroita merkkijonoina 64-bittisten kokonaislukujen tarkkuuden menetyksen estämiseksi. v1:n käyttäytyminen oli rajoitettua ja epäjohdonmukaista. v2 keskittyy tähän ydinkäyttötarkoitukseen ja laajentaa käyttäytymistä rekursiivisesti tehdäkseen siitä hyödyllisemmän. - Liittyvät Options:
json.StringifyWithLegacySemantics(true)
-optiolla voidaan jäljitellä v1:n käyttäytymistä.
4. nil
-viipaleiden ja mappien Marshalling
- v1-käyttäytyminen:
nil
-viipaleet janil
-mapit marshalloidaannull
-arvoksi. - v2-käyttäytyminen: Oletuksena
nil
-viipaleet marshalloidaan[]
(tyhjä taulukko) janil
-mapit{}
(tyhjä objekti) -arvoiksi. - Muutoksen syy:
nil
on Go-kielen toteutuksen yksityiskohta, ja sen paljastaminen kielestä riippumattomalle JSON-muodolle ei ole suotavaa. Tyhjää kokoelmaa edustavat[]
tai{}
ovat yleisempiä ilmaisutapoja. - Liittyvät Options: V2:ssa voidaan marshalloida
null
-arvoksi kuten v1:ssä käyttämälläjson.FormatNilSliceAsNull(true)
taijson.FormatNilMapAsNull(true)
-optioita.
5. Taulukon unmarshalling
- v1-käyttäytyminen: Kun puretaan Go-taulukkoon (
[N]T
), virhettä ei synny, vaikka JSON-taulukon pituus eroaisi Go-taulukon pituudesta. Jos pituus on lyhyempi, jäljelle jäävä tila täytetään nolla-arvoilla; jos pituus on pidempi, ylimääräiset osat hylätään. - v2-käyttäytyminen: JSON-taulukon pituuden on vastattava tarkalleen Go-taulukon pituutta. Muussa tapauksessa syntyy virhe.
- Muutoksen syy: Go:ssa kiinteäkokoisilla taulukoilla on usein merkitystä niiden pituuden osalta. v1:n käyttäytyminen voi aiheuttaa äänetöntä tiedon menetystä. v2 lisää tarkkuutta tiukemmilla säännöillä.
- Liittyvät Options:
json.UnmarshalArrayFromAnyLength(true)
-optiolla voidaan jäljitellä v1:n käyttäytymistä.
6. time.Duration
-käsittely
- v1-käyttäytyminen:
time.Duration
käsitellään sisäisestiint64
-tyyppinä ja koodataan JSON-numeroksi nanosekunteina. - v2-käyttäytyminen: Käyttää
time.Duration.String()
-metodia koodatakseen JSON-merkkijonoksi muodossa"1h2m3s"
. - Muutoksen syy: Numeeriset nanosekunnit ovat hankalasti luettavissa, ja
time.Duration
-tyypin standardimerkkijonoesitys on hyödyllisempi. - Liittyvät Options: V1:n käyttäytymistä voidaan käyttää
json:",format:nano"
-tag-option taijson.FormatTimeWithLegacySemantics(true)
-option kautta.
7. Virheellisen UTF-8:n käsittely
- v1-käyttäytyminen: Jos merkkijonossa on virheellisiä UTF-8-tavuja marshalloinnin/unmarshalloinnin aikana, ne korvataan äänettömästi Unicode-korvausmerkillä (
\uFFFD
). - v2-käyttäytyminen: Oletuksena, jos virheellinen UTF-8 havaitaan, palautetaan virhe.
- Muutoksen syy: Estää tiedon äänettömän korruption ja noudattaa tiukempia JSON-standardeja (RFC 7493).
- Liittyvät Options:
jsontext.AllowInvalidUTF8(true)
-optiolla voidaan jäljitellä v1:n käyttäytymistä.
8. Päällekkäisten objektijäsenien nimien käsittely
- v1-käyttäytyminen: Sallii samannimisten jäsenien esiintymisen useaan kertaan JSON-objektissa. Viimeksi esiintynyt arvo korvaa aiemmat.
- v2-käyttäytyminen: Oletuksena, jos on päällekkäisiä jäsenien nimiä, palautetaan virhe.
- Muutoksen syy: RFC 8259 -standardi ei määrittele päällekkäisten nimien käyttäytymistä, joten toteutukset voivat toimia eri tavoin. Tämä voi aiheuttaa tietoturva-aukkoja. v2 kieltää sen nimenomaisesti lisätäkseen tarkkuutta ja turvallisuutta.
- Liittyvät Options:
jsontext.AllowDuplicateNames(true)
-optiolla voidaan jäljitellä v1:n käyttäytymistä.
Toteutus- ja arkkitehtuurierot
- v1: Riippuu vahvasti
decode.go
-tiedostondecodeState
-tilasta jascanner.go
-tiedoston käsin kirjoitetusta tilakoneesta (state machine). Tämä on monoliittinen rakenne, jossa jäsennyslogiikka ja semanttinen analyysi ovat tiiviisti sidoksissa. - v2: Arkkitehtuuri on modulaarisempi.
encoding/json/jsontext
: Tarjoaa matalan tason, tehokkaan JSON-tokenoijan (Decoder
) ja kooderin (Encoder
). Tämä paketti keskittyy ainoastaan JSON:n syntaksillisiin näkökohtiin.encoding/json/v2
: Käsittelee semanttisia muunnoksia Go-tyyppien ja JSON-arvojen välilläjsontext
-paketin pohjalta.- Tämä erottelu parantaa koodin selkeyttä ja suorituskykyä, koska syntaksianalyysi ja semanttinen analyysi on erotettu.
V2:n uudet API:t ja ominaisuudet
V2 tarjoaa erittäin joustavat ohjausominaisuudet json.Options
-järjestelmän kautta.
json.Options
: Kokoelma vaihtoehtoja, jotka muuttavat marshalloinnin/unmarshalloinnin käyttäytymistä.json.JoinOptions(...)
: Yhdistää useita vaihtoehtoja yhdeksi.WithMarshalers
/WithUnmarshalers
: Tehokas ominaisuus, joka mahdollistaa serialisointi-/deserialisointilogiikan injektoimisen tietyille tyypeille ilman, että tarvitsee toteuttaaMarshaler
/Unmarshaler
-rajapintaa. Tämä on erityisen hyödyllistä käsiteltäessä ulkoisten pakettien tyyppejä.- Uudet Options:
RejectUnknownMembers
,Deterministic(false)
,FormatNilSliceAsNull
ja monet muut, joita ei ollut mahdollista hallita v1:ssä.
Johtopäätös
encoding/json
v2 on moderni toteutus, joka on merkittävästi parantanut tarkkuutta, suorituskykyä ja joustavuutta v1:n kokemusten perusteella. Vaikka sen oletuskäyttäytyminen on tiukempi, sen hienostunut Options
-järjestelmä tukee täysin kaikkea v1:n käyttäytymistä, mikä mahdollistaa v2:n etujen asteittaisen käyttöönoton säilyttäen yhteensopivuuden olemassa olevan koodin kanssa.
- Uusissa projekteissa on suositeltavaa käyttää v2:ta oletuksena.
- Olemassa olevat projektit voivat jatkaa
jsonv1
:n käyttöä tai siirtyäjsonv2
:een ja ottaa asteittain käyttöön v2:n tiukemman käyttäytymisenDefaultOptionsV1()
-funktion kautta.