Json in Groovy

import groovy.json.JsonBuilder
import groovy.json.JsonSlurper

// We'll use these two classes to demonstrate encoding and
// decoding of custom types below.
class Response1 {
    int page
    List<String> fruits
}

// Only properties will be encoded/decoded in JSON.
// We can use annotations to customize the JSON key names.
class Response2 {
    @JsonProperty('page')
    int page
    
    @JsonProperty('fruits')
    List<String> fruits
}

// First we'll look at encoding basic data types to
// JSON strings. Here are some examples for atomic values.
def bolB = new JsonBuilder(true).toString()
println bolB

def intB = new JsonBuilder(1).toString()
println intB

def fltB = new JsonBuilder(2.34).toString()
println fltB

def strB = new JsonBuilder("gopher").toString()
println strB

// And here are some for lists and maps, which encode
// to JSON arrays and objects as you'd expect.
def slcD = ["apple", "peach", "pear"]
def slcB = new JsonBuilder(slcD).toString()
println slcB

def mapD = [apple: 5, lettuce: 7]
def mapB = new JsonBuilder(mapD).toString()
println mapB

// The JSON package can automatically encode your
// custom data types. It will only include properties
// in the encoded output and will by default
// use those names as the JSON keys.
def res1D = new Response1(page: 1, fruits: ["apple", "peach", "pear"])
def res1B = new JsonBuilder(res1D).toString()
println res1B

// You can use annotations on class properties
// to customize the encoded JSON key names. Check the
// definition of `Response2` above to see an example
// of such annotations.
def res2D = new Response2(page: 1, fruits: ["apple", "peach", "pear"])
def res2B = new JsonBuilder(res2D).toString()
println res2B

// Now let's look at decoding JSON data into Groovy
// values. Here's an example for a generic data
// structure.
def byt = '{"num":6.13,"strs":["a","b"]}'

// We need to provide a variable where the JSON
// package can put the decoded data. This
// will hold a map of strings to arbitrary data types.
def dat = new JsonSlurper().parseText(byt)
println dat

// In order to use the values in the decoded map,
// we can access them directly. Groovy will automatically
// convert them to the appropriate type.
def num = dat.num
println num

// Accessing nested data is straightforward in Groovy.
def str1 = dat.strs[0]
println str1

// We can also decode JSON into custom data types.
// This has the advantages of adding additional
// type-safety to our programs and eliminating the
// need for type assertions when accessing the decoded
// data.
def str = '{"page": 1, "fruits": ["apple", "peach"]}'
def res = new JsonSlurper().parseText(str) as Response2
println res
println res.fruits[0]

// In the examples above we always used strings as
// intermediates between the data and JSON representation.
// We can also stream JSON encodings directly to writers
// like System.out or even HTTP response bodies.
def d = [apple: 5, lettuce: 7]
System.out << new JsonBuilder(d).toPrettyString()

This Groovy code demonstrates JSON encoding and decoding, including working with custom classes, maps, and lists. It uses the groovy.json.JsonBuilder for encoding and groovy.json.JsonSlurper for decoding.

The structure and explanations from the original Go example have been maintained, but adapted to Groovy’s syntax and conventions. For instance, Groovy’s dynamic typing allows for more straightforward JSON parsing without explicit type conversions.

To run this Groovy script, save it to a file (e.g., json_example.groovy) and execute it using the groovy command:

$ groovy json_example.groovy

This will output the results of the various JSON encoding and decoding operations demonstrated in the script.