GoSuda

Go 1.25 encoding/json v1 vs v2 -vertailu

By lemonmint
views ...

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:

  1. 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ä.
  2. Suorituskyvyn parantaminen: Jäsennys- ja koodausmoottorit on suunniteltu uudelleen tehokkuuden lisäämiseksi.
  3. 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" kartoitetaan FirstName-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 soveltamaan json.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-tyypin false-arvo jätetään pois, mutta v2:ssa false ei ole tyhjä JSON-arvo, joten sitä ei jätetä pois. V2:ssa on lisätty omitzero-optio, jolla voidaan korvata v1:n omitempty-käyttäytyminen, joka koski 0 tai false.
  • 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 ja nil-mapit marshalloidaan null-arvoksi.
  • v2-käyttäytyminen: Oletuksena nil-viipaleet marshalloidaan [] (tyhjä taulukko) ja nil-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) tai json.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äisesti int64-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 tai json.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-tiedoston decodeState-tilasta ja scanner.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 toteuttaa Marshaler/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äytymisen DefaultOptionsV1()-funktion kautta.