ohler55 / ojg

Optimized JSON for Go
MIT License
857 stars 49 forks source link

Inconsitent capitalization and loss of capitalization in pretty.JSON for structs #165

Closed Skeeve closed 8 months ago

Skeeve commented 8 months ago

Hi.

In my program I parse a custom struct. Everything works as expected, except when I pretty.JSON print my data.

Capitalization is lost for all type properties. On the other hand is it taken into account when searching for properties.

Please find below example program on the playground.

I have the (almost) same structure (taken from #111) once as a parsed JSON string (data) and once (data2) as a struct.

Please observe that Locate on the struct finds both name and Name when searching for "Name" but only 'name'. when searching for "name".

Also only the parsed data is printed correctly while the struct data2 lost its capitalization.

package main

import (
    "fmt"
    "github.com/ohler55/ojg/jp"
    "github.com/ohler55/ojg/oj"
    "github.com/ohler55/ojg/pretty"
)

type capitaltest struct{
    Name string
    Male bool
    Age int
    Address string
    Metadata map[string]string
    Test map[string]string
}

func main() {
    jsonDataString := `{
        "Name": "John Smith",
        "Male": true,
        "Age": 35,
        "Address": "New York",
        "Null": null,
        "Metadata": {
            "Date": "2022-04-01T00:00:00.000Z",
            "Count": "5",
            "Name": "John Smith"
        },
        "Test": {
            "Name": "John Smith"
        }
    }`
    data, _ := oj.ParseString(jsonDataString)
    fmt.Println(pretty.JSON(data))

    myUp := jp.MustParseString(`$..Name`)
    myLow := jp.MustParseString(`$..name`)

    myLoc := myUp.Locate(data, 0)
    fmt.Printf("Searched 'Name': %+v\n", myLoc)
    myLoc = myLow.Locate(data, 0)
    fmt.Printf("Searched 'name': %+v\n", myLoc)

    data2 := capitaltest{
        Name: "John Smith",
        Male: true,
        Age: 35,
        Address: "New York",
        Metadata: map[string]string{
            "Date": "2022-04-01T00:00:00.000Z",
            "Count": "5",
            "Name": "John Smith",
        },
        Test: map[string]string{
            "Name": "John Smith",
        },
    }
    fmt.Println(pretty.JSON(data2))

    myLoc = myUp.Locate(data2, 0)
    fmt.Printf("Searched 'Name': %+v\n", myLoc)
    myLoc = myLow.Locate(data2, 0)
    fmt.Printf("Searched 'name': %+v\n", myLoc)
}

Output:

{
  "Address": "New York",
  "Age": 35,
  "Male": true,
  "Metadata": {"Count": "5", "Date": "2022-04-01T00:00:00.000Z", "Name": "John Smith"},
  "Name": "John Smith",
  "Null": null,
  "Test": {"Name": "John Smith"}
}
Searched 'Name': [$.Name $.Metadata.Name $.Test.Name]
Searched 'name': []
{
  "address": "New York",
  "age": 35,
  "male": true,
  "metadata": {"Count": "5", "Date": "2022-04-01T00:00:00.000Z", "Name": "John Smith"},
  "name": "John Smith",
  "test": {"Name": "John Smith"}
}
Searched 'Name': [$.Name $.Test.Name $.Metadata.Name]
Searched 'name': [$.name]
ohler55 commented 8 months ago

Please take a look at the Options struct. You can configure the output in many different ways when it is passed to pretty.JSON() or my preferred pretty.SEN().

Skeeve commented 8 months ago

I tried to but didn't get it.

fmt.Println(pretty.JSON(data2, oj.Options{KeyExact: true}))

is what I tried and still the keys were lowercase.

OTOH: "data.Name" is found when searching "name" which I think is an error.

ohler55 commented 8 months ago

Try fmt.Println(pretty.JSON(data2, &oj.Options{KeyExact: true})) instead.

The searches are not case sensitive when search the field on a struct. The reason for that is that private struct names, those starting with a lowercase letter are not accessible so it doesn't make sense to search for a private field. You will probably find that in most cases camelBack names are used in JSON so it is reasonable to support that as the default behavior.

Skeeve commented 8 months ago

Thanks for your explanation.

Casing is correct now and the search-thing I understood.