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:ssafalseei 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 koski0taifalse. - 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:
nilon 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.Durationkä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),FormatNilSliceAsNullja 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.