id.go 1.7 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576
  1. package jsonschema
  2. import (
  3. "errors"
  4. "fmt"
  5. "net/url"
  6. "strings"
  7. )
  8. // ID represents a Schema ID type which should always be a URI.
  9. // See draft-bhutton-json-schema-00 section 8.2.1
  10. type ID string
  11. // EmptyID is used to explicitly define an ID with no value.
  12. const EmptyID ID = ""
  13. // Validate is used to check if the ID looks like a proper schema.
  14. // This is done by parsing the ID as a URL and checking it has all the
  15. // relevant parts.
  16. func (id ID) Validate() error {
  17. u, err := url.Parse(id.String())
  18. if err != nil {
  19. return fmt.Errorf("invalid URL: %w", err)
  20. }
  21. if u.Hostname() == "" {
  22. return errors.New("missing hostname")
  23. }
  24. if !strings.Contains(u.Hostname(), ".") {
  25. return errors.New("hostname does not look valid")
  26. }
  27. if u.Path == "" {
  28. return errors.New("path is expected")
  29. }
  30. if u.Scheme != "https" && u.Scheme != "http" {
  31. return errors.New("unexpected schema")
  32. }
  33. return nil
  34. }
  35. // Anchor sets the anchor part of the schema URI.
  36. func (id ID) Anchor(name string) ID {
  37. b := id.Base()
  38. return ID(b.String() + "#" + name)
  39. }
  40. // Def adds or replaces a definition identifier.
  41. func (id ID) Def(name string) ID {
  42. b := id.Base()
  43. return ID(b.String() + "#/$defs/" + name)
  44. }
  45. // Add appends the provided path to the id, and removes any
  46. // anchor data that might be there.
  47. func (id ID) Add(path string) ID {
  48. b := id.Base()
  49. if !strings.HasPrefix(path, "/") {
  50. path = "/" + path
  51. }
  52. return ID(b.String() + path)
  53. }
  54. // Base removes any anchor information from the schema
  55. func (id ID) Base() ID {
  56. s := id.String()
  57. i := strings.LastIndex(s, "#")
  58. if i != -1 {
  59. s = s[0:i]
  60. }
  61. s = strings.TrimRight(s, "/")
  62. return ID(s)
  63. }
  64. // String provides string version of ID
  65. func (id ID) String() string {
  66. return string(id)
  67. }