parse.go 1.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051
  1. package initdata
  2. import (
  3. "encoding/json"
  4. "fmt"
  5. "net/url"
  6. "strings"
  7. )
  8. var (
  9. // List of properties which should always be interpreted as strings.
  10. _stringProps = map[string]bool{
  11. "start_param": true,
  12. }
  13. )
  14. // Parse converts passed init data presented as query string to InitData
  15. // object.
  16. func Parse(initData string) (InitData, error) {
  17. // Parse passed init data as query string.
  18. q, err := url.ParseQuery(initData)
  19. if err != nil {
  20. return InitData{}, ErrUnexpectedFormat
  21. }
  22. // According to documentation, we could only meet such types as int64,
  23. // string, or another object. So, we create
  24. pairs := make([]string, 0, len(q))
  25. for k, v := range q {
  26. // Derive real value. We know that there can not be any arrays and value
  27. // can be the only one.
  28. val := v[0]
  29. valFormat := "%q:%q"
  30. // If passed value is valid in the context of JSON, it means, we could
  31. // insert this value without formatting.
  32. if isString := _stringProps[k]; !isString && json.Valid([]byte(val)) {
  33. valFormat = "%q:%s"
  34. }
  35. pairs = append(pairs, fmt.Sprintf(valFormat, k, val))
  36. }
  37. // Unmarshal JSON to our custom structure.
  38. var d InitData
  39. jStr := fmt.Sprintf("{%s}", strings.Join(pairs, ","))
  40. if err := json.Unmarshal([]byte(jStr), &d); err != nil {
  41. return InitData{}, ErrUnexpectedFormat
  42. }
  43. return d, nil
  44. }