{"id":13645693,"url":"https://github.com/amazon-ion/ion-go","last_synced_at":"2025-05-07T19:15:10.301Z","repository":{"id":44531138,"uuid":"234407137","full_name":"amazon-ion/ion-go","owner":"amazon-ion","description":"A Go implementation of Amazon Ion.","archived":false,"fork":false,"pushed_at":"2024-06-06T21:35:55.000Z","size":645,"stargazers_count":178,"open_issues_count":39,"forks_count":31,"subscribers_count":14,"default_branch":"master","last_synced_at":"2025-05-07T19:15:03.566Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"https://amazon-ion.github.io/ion-docs/","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/amazon-ion.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2020-01-16T20:37:16.000Z","updated_at":"2025-04-08T16:58:33.000Z","dependencies_parsed_at":"2024-01-14T09:57:23.918Z","dependency_job_id":"ea47f7d8-ad24-4b13-b472-32fbff9d942d","html_url":"https://github.com/amazon-ion/ion-go","commit_stats":{"total_commits":159,"total_committers":22,"mean_commits":"7.2272727272727275","dds":0.7106918238993711,"last_synced_commit":"c017c29e6d8c5a3c75fea9a5be1796288f0a412c"},"previous_names":["amzn/ion-go"],"tags_count":13,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/amazon-ion%2Fion-go","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/amazon-ion%2Fion-go/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/amazon-ion%2Fion-go/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/amazon-ion%2Fion-go/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/amazon-ion","download_url":"https://codeload.github.com/amazon-ion/ion-go/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":252940903,"owners_count":21828769,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-08-02T01:02:39.806Z","updated_at":"2025-05-07T19:15:10.270Z","avatar_url":"https://github.com/amazon-ion.png","language":"Go","funding_links":[],"categories":["Go"],"sub_categories":[],"readme":"# Amazon Ion Go\n\n[![Build Status](https://github.com/amazon-ion/ion-go/workflows/Go%20Build/badge.svg)](https://github.com/amazon-ion/ion-go/actions?query=workflow%3A%22Go+Build%22)\n[![license](https://img.shields.io/hexpm/l/plug.svg)](https://github.com/amazon-ion/ion-go/blob/master/LICENSE)\n[![docs](https://img.shields.io/badge/docs-api-green.svg)](https://pkg.go.dev/github.com/amazon-ion/ion-go?tab=doc)\n\nAmazon Ion ( https://amazon-ion.github.io/ion-docs/ ) library for Go\n\n[Ion Cookbook](https://amazon-ion.github.io/ion-docs/guides/cookbook.html) demonstrates code samples for some simple Amazon Ion use cases.\n\nThis package is based on work from David Murray ([fernomac](https://github.com/fernomac/)) on https://github.com/fernomac/ion-go.\nThe Ion team greatly appreciates David's contributions to the Ion community.\n\n\n## Users\n\nHere are some projects that use the Ion Go library\n\n* [Restish](https://rest.sh/): \"...a CLI for interacting with REST-ish HTTP APIs with some nice features built-in\"\n\n\nWe'll be happy to add you to our list, send us a pull request.\n\n\n## Git Setup\n\n\nThis repository contains a [git submodule](https://git-scm.com/docs/git-submodule)\ncalled `ion-tests`, which holds test data used by `ion-go`'s unit tests.\n\nThe easiest way to clone the `ion-go` repository and initialize its `ion-tests`\nsubmodule is to run the following command.\n\n```\n$ git clone --recursive https://github.com/amazon-ion/ion-go.git ion-go\n```\n\nAlternatively, the submodule may be initialized independent of the clone\nby running the following commands:\n\n```\n$ git submodule init\n$ git submodule update\n```\n\n## Development\n\nThis package uses [Go Modules](https://github.com/golang/go/wiki/Modules) to model\nits dependencies.\n\nAssuming the `go` command is in your path, building the module can be done as:\n\n```\n$ go build -v ./...\n```\n\nRunning all the tests can be executed with:\n\n```\n$ go test -v ./...\n```\n\nWe use [`goimports`](https://pkg.go.dev/golang.org/x/tools/cmd/goimports?tab=doc) to format\nour imports and files in general.  Running this before commit is advised:\n\n```\n$ goimports -w .\n```\n\nIt is recommended that you hook this in your favorite IDE (`Tools` \u003e `File Watchers` in Goland, for example).\n\n## Usage\n\nImport `github.com/amazon-ion/ion-go/ion` and you're off to the races.\n\n### Marshaling and Unmarshaling\n\nSimilar to GoLang's built-in [json](https://golang.org/pkg/encoding/json/) package,\nyou can marshal and unmarshal Go types to Ion. Marshaling requires you to specify\nwhether you'd like text or binary Ion. Unmarshaling is smart enough to do the right\nthing. Both follow the style of json name tags, and `Marshal` honors `omitempty`.\n\n```Go\ntype T struct {\n  A string\n  B struct {\n    RenamedC int   `ion:\"C\"`\n    D        []int `ion:\",omitempty\"`\n  }\n}\n\nfunc main() {\n  t := T{}\n\n  err := ion.Unmarshal([]byte(`{A:\"Ion!\",B:{C:2,D:[3,4]}}`), \u0026t)\n  if err != nil {\n    panic(err)\n  }\n  fmt.Printf(\"--- t:\\n%v\\n\\n\", t)\n\n  text, err := ion.MarshalText(\u0026t)\n  if err != nil {\n    panic(err)\n  }\n  fmt.Printf(\"--- text:\\n%s\\n\\n\", string(text))\n\n  binary, err := ion.MarshalBinary(\u0026t)\n  if err != nil {\n    panic(err)\n  }\n  fmt.Printf(\"--- binary:\\n%X\\n\\n\", binary)\n}\n```\n\nIn order to Marshal/Unmarshal Ion values with annotation, we use a Go struct with two fields,\n\n1. one field of type `[]string` and tagged  with `ion:\",annotation\"`.\n2. the other field with appropriate type and optional tag to hold our Ion value. For instance,\nto Marshal `age::20`, it must be in a struct as below:\n```GO\n  type foo struct {\n    Value   interface{}\n    AnyName []string `ion:\",annotations\"`\n  }\n  data := foo{20, []string{\"age\"}}\n  val, err := ion.MarshalText(data)\n  if err != nil {\n     panic(err)\n  }\n  fmt.Println(\"Ion text: \", string(val)) // Ion text: age::20\n```\n\nAnd to Unmarshal the same data, we can do as shown below:\n```Go\n  type foo struct {\n    Value   interface{}\n    AnyName []string `ion:\",annotations\"`\n  }\n  var val foo\n  err := ion.UnmarshalString(\"age::20\", \u0026val)\n  if err != nil {\n    panic(err)\n  }\n  fmt.Printf(\"Val = %+v\\n\", val) // Val = {Value:20 AnyName:[age]}\n```\n\n\n### Encoding and Decoding\n\nTo read or write multiple values at once, use an `Encoder` or `Decoder`:\n\n```Go\nfunc main() {\n  dec := ion.NewTextDecoder(os.Stdin)\n  enc := ion.NewBinaryEncoder(os.Stdout)\n\n  for {\n    // Decode one Ion whole value from stdin.\n    val, err := dec.Decode()\n    if err == ion.ErrNoInput {\n      break\n    } else if err != nil {\n      panic(err)\n    }\n\n    // Encode it to stdout.\n    if err := enc.Encode(val); err != nil {\n      panic(err)\n    }\n  }\n\n  if err := enc.Finish(); err != nil {\n    panic(err)\n  }\n}\n```\n\n### Reading and Writing\n\nFor low-level streaming read and write access, use a `Reader` or `Writer`.\nThe following example shows how to create a reader, read values from that reader,\nand write those values out using a writer:\n\n```Go\nfunc writeFromReaderToWriter(reader Reader, writer Writer) {\n\tfor reader.Next() {\n\t\tname := reader.FieldName()\n\t\tif name != nil {\n\t\t\terr := writer.FieldName(*name)\n\t\t\tif err != nil {\n\t\t\t\tpanic(err)\n\t\t\t}\n\t\t}\n\n\t\tan := reader.Annotations()\n\t\tif len(an) \u003e 0 {\n\t\t\terr := writer.Annotations(an...)\n\t\t\tif err != nil {\n\t\t\t\tpanic(err)\n\t\t\t}\n\t\t}\n\n\t\tcurrentType := reader.Type()\n\t\tif reader.IsNull() {\n\t\t\terr := writer.WriteNullType(currentType)\n\t\t\tif err != nil {\n\t\t\t\tpanic(err)\n\t\t\t}\n\t\t\tcontinue\n\t\t}\n\n\t\tswitch currentType {\n\t\tcase BoolType:\n\t\t\tval, err := reader.BoolValue()\n\t\t\tif err != nil {\n\t\t\t\tpanic(\"Something went wrong while reading a Boolean value: \" + err.Error())\n\t\t\t}\n\t\t\terr = writer.WriteBool(val)\n\t\t\tif err != nil {\n\t\t\t\tpanic(\"Something went wrong while writing a Boolean value: \" + err.Error())\n\t\t\t}\n\n\t\tcase StringType:\n\t\t\tval, err := reader.StringValue()\n\t\t\tif err != nil {\n\t\t\t\tpanic(\"Something went wrong while reading a String value: \" + err.Error())\n\t\t\t}\n\t\t\terr = writer.WriteString(val)\n\t\t\tif err != nil {\n\t\t\t\tpanic(\"Something went wrong while writing a String value: \" + err.Error())\n\t\t\t}\n\n\t\tcase StructType:\n\t\t\terr := reader.StepIn()\n\t\t\tif err != nil {\n\t\t\t\tpanic(err)\n\t\t\t}\n\t\t\terr = writer.BeginStruct()\n\t\t\tif err != nil {\n\t\t\t\tpanic(err)\n\t\t\t}\n\t\t\twriteFromReaderToWriter(reader, writer)\n\t\t\terr = reader.StepOut()\n\t\t\tif err != nil {\n\t\t\t\tpanic(err)\n\t\t\t}\n\t\t\terr = writer.EndStruct()\n\t\t\tif err != nil {\n\t\t\t\tpanic(err)\n\t\t\t}\n        default:\n            panic(\"This is an example, only taking in Bool, String and Struct\")\n\t\t}\n\t}\n\n\tif reader.Err() != nil {\n\t\tpanic(reader.Err().Error())\n\t}\n}\n\nfunc main() {\n\treader := NewReaderString(\"foo::{name:\\\"bar\\\", complete:false}\")\n\tstr := strings.Builder{}\n\twriter := NewTextWriter(\u0026str)\n\n\twriteFromReaderToWriter(reader, writer)\n\terr := writer.Finish()\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\tfmt.Println(str.String())\n}\n```\n\n### Symbol Tables\n\nBy default, when writing binary Ion, a local symbol table is built as you write\nvalues (which are buffered in memory until you call `Finish` so the symbol table\ncan be written out first). You can optionally provide one or more\n`SharedSymbolTable`s to the writer, which it will reference as needed rather\nthan directly including those symbols in the local symbol table.\n\n```Go\ntype Item struct {\n  ID          string    `ion:\"id\"`\n  Name        string    `ion:\"name\"`\n  Description string    `ion:\"description\"`\n}\n\nvar ItemSharedSymbols = ion.NewSharedSymbolTable(\"item\", 1, []string{\n  \"item\",\n  \"id\",\n  \"name\",\n  \"description\",\n})\n\ntype SpicyItem struct {\n  Item\n  Spiciness   int       `ion:\"spiciness\"`\n}\n\nfunc WriteSpicyItemsTo(out io.Writer, items []SpicyItem) error {\n  writer := ion.NewBinaryWriter(out, ItemSharedSymbols)\n\n  for _, item := range items {\n    writer.Annotation(\"item\")\n    if err := ion.EncodeTo(writer, item); err != nil {\n      return err\n    }\n  }\n\n  return writer.Finish()\n}\n```\n\nYou can alternatively provide the writer with a complete, pre-built local symbol table.\nThis allows values to be written without buffering, however any attempt to write a\nsymbol that is not included in the symbol table will result in an error:\n\n```Go\nfunc WriteItemsToLST(out io.Writer, items []SpicyItem) error {\n  lst := ion.NewLocalSymbolTable([]SharedSymbolTable{ItemSharedSymbols}, []string{\n    \"spiciness\",\n  })\n\n  writer := ion.NewBinaryWriterLST(out, lst)\n\n  for _, item := range items {\n    writer.Annotation(\"item\")\n    if err := ion.EncodeTo(writer, item); err != nil {\n      return err\n    }\n  }\n\n  return writer.Finish()\n}\n```\n\nWhen reading binary Ion, shared symbol tables are provided by a `Catalog`. A basic\ncatalog can be constructed by calling `NewCatalog`; a smarter implementation may\nload shared symbol tables from a database on demand.\n\n```Go\n\nfunc ReadItemsFrom(in io.Reader) ([]Item, error) {\n  item := Item{}\n  items := []Item{}\n\n  cat := ion.NewCatalog(ItemSharedSymbols)\n  dec := ion.NewDecoder(ion.NewReaderCat(in, cat))\n\n  for {\n    err := dec.DecodeTo(\u0026item)\n    if err == ion.ErrNoInput {\n      return items, nil\n    }\n    if err != nil {\n      return nil, err\n    }\n\n    items = append(items, item)\n  }\n}\n```\n### License\n\nThis library is licensed under the Apache 2.0 License.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Famazon-ion%2Fion-go","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Famazon-ion%2Fion-go","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Famazon-ion%2Fion-go/lists"}