0

In the json package if you want to utilize tags to marshall and unmarshall structs the field must be exported. I always thought this was a limitation on the reflect package but it seems to be explicitly rejected here.

I would like to know what I am missing or the design choices behind this as it creates one of the following issues normally.

  1. Exporting more fields than I want allowing users to change values without using potential getters and setters.
  2. A lot of extra code if you chose to solve the above problem by making a second identical struct just for tag usage and make it unexported.

Here is a playground of code being able to read unexported tags.

Edit: Better playground thanks to @mkopriva

Stephen
  • 56
  • 7
  • 1
    A tag by itself, without the field's value, is useless for JSON. And reading tags of unexported fields is NOT the same as reading the values of unxported fields. Tags are used only for field names in the JSON, you can't use them to populate those fields with actual JSON values, for that you need an exported field's value, not a tag. See https://go.dev/play/p/KnSSsQ85vzV. – mkopriva Jul 17 '22 at 14:36
  • I now see that the concern is pointers in the reflect package, thank you. At the same time [here](https://go.dev/play/p/lkIZA1lPgYN) is a working version of your example. I could be wrong but I think it is accessing the data safely(without unsafe pointers). @mkopriva – Stephen Jul 17 '22 at 16:19
  • That's only good for strings, any other type will panic. And `String() string` doesn't panic only because of the `fmt.Stringer` convention, see [docs](https://pkg.go.dev/reflect@go1.18.4#Value.String): *"String is a special case because of Go's String method convention. Unlike the other getters, it does not panic if v's Kind is not String."* If it wasn't for that convention your example would panic as well. – mkopriva Jul 17 '22 at 16:38
  • There is a getter for every basic type It would require an extensive switch statement to handle all `reflect.kinds` but it is not because string is special https://go.dev/play/p/Kqc6H8woRwT. @mkopriva – Stephen Jul 17 '22 at 17:12
  • Ah yes, my bad, that part's about the kind not the "exportedness". Still, though, even if you're able to get a copy of basic value you're unable to set unexported fields, which, if you had your wish fulfilled, would make the json api inconsistent. – mkopriva Jul 17 '22 at 17:20
  • Value are able to be set using unsafe pointers https://stackoverflow.com/questions/42664837/how-to-access-unexported-struct-fields. I think this is a a rare valid reason to use unsafe pointers. @mkopriva. Sorry if the @'s are annoying I am not sure if they are necessary to ping you. – Stephen Jul 17 '22 at 17:43
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/246514/discussion-between-stephen-and-mkopriva). – Stephen Jul 17 '22 at 18:01

0 Answers0