Skip to content

Instantly share code, notes, and snippets.

@sp3c73r2038
Created May 25, 2020 07:25
Show Gist options
  • Select an option

  • Save sp3c73r2038/7feb724c892cb30086c9d26b823646ba to your computer and use it in GitHub Desktop.

Select an option

Save sp3c73r2038/7feb724c892cb30086c9d26b823646ba to your computer and use it in GitHub Desktop.

Revisions

  1. sp3c73r2038 created this gist May 25, 2020.
    88 changes: 88 additions & 0 deletions jc.go
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,88 @@
    package main

    import (
    "encoding/json"
    "fmt"
    "io/ioutil"
    "log"
    "os"
    )

    func must(err error) {
    if err != nil {
    log.Fatal(err)
    }
    }

    func main() {

    args := os.Args[1:]
    if len(args) <= 0 {
    fmt.Printf("usage: %s <file> \n", os.Args[0])
    os.Exit(1)
    }

    b, err := ioutil.ReadFile(args[0])
    must(err)

    var v interface{}
    err = json.Unmarshal(b, &v)

    // https: //adrianhesketh.com/2017/03/18/getting-line-and-character-positions-from-gos-json-unmarshal-errors/

    if jsonError, ok := err.(*json.SyntaxError); ok {
    line, character, lcErr := lineAndCharacter(string(b), int(jsonError.Offset))
    fmt.Fprintf(
    os.Stderr,
    "Cannot parse JSON schema due to a syntax error at line %d, character %d: %v\n",
    line, character, jsonError.Error())
    if lcErr != nil {
    fmt.Fprintf(
    os.Stderr,
    "Couldn't find the line and character position of the error due to error %v\n",
    lcErr)
    }
    os.Exit(1)
    }
    if jsonError, ok := err.(*json.UnmarshalTypeError); ok {
    line, character, lcErr := lineAndCharacter(string(b), int(jsonError.Offset))
    fmt.Fprintf(
    os.Stderr,
    "The JSON type '%v' cannot be converted into the Go '%v' type on struct "+
    "'%s', field '%v'. See input file line %d, character %d\n",
    jsonError.Value, jsonError.Type.Name(), jsonError.Struct,
    jsonError.Field, line, character)
    if lcErr != nil {
    fmt.Fprintf(
    os.Stderr,
    "Couldn't find the line and character position of the error due to error %v\n",
    lcErr)
    }
    os.Exit(1)
    }
    os.Exit(0)
    }

    func lineAndCharacter(input string, offset int) (line int, character int, err error) {
    lf := rune(0x0A)

    if offset > len(input) || offset < 0 {
    return 0, 0, fmt.Errorf("Couldn't find offset %d within the input.", offset)
    }

    // Humans tend to count from 1.
    line = 1

    for i, b := range input {
    if b == lf {
    line++
    character = 0
    }
    character++
    if i == offset {
    break
    }
    }

    return line, character, nil
    }