qri-io/dataset

need to always be able to marshal to json for dataset subcomponents

Closed this issue · 0 comments

MarshalJSON() methods for Meta, Structure, VisConfig, Transform, Commit may marshal to either a string (if the structure is a reference--which means its internal path parameter is set and its IsEmpty() method returns true):

[]byte(`"meta": "/ipfs/Qm1234..."`)

or an object:

[]byte(`"meta": { ... }`)

but in certain cases (such as comparing the objects inside datasetDiffer, where we assume that objects have been fully de-referenced) we need to always marshal to an object. To facilitate this the MarshalJSON methods for each need to be refactored to expose an exported MarshalJSONObject() method. This has already been done for Meta, shown below:

func (md *Meta) MarshalJSON() ([]byte, error) {
	// if we're dealing with an empty object that has a path specified, marshal to a string instead
	// TODO - check all fielmd
	if md.path.String() != "" && md.IsEmpty() {
		return md.path.MarshalJSON()
	}

	return md.MarshalJSONObject()
}

// MarshalJSONObject always marshals to a json Object, even if meta is empty or a reference
func (md *Meta) MarshalJSONObject() ([]byte, error) {
	data := md.Meta()

	data["qri"] = KindMeta

	if md.AccessPath != "" {
		data["accessPath"] = md.AccessPath
	}
	if md.Citations != nil {
		data["citations"] = md.Citations
	}
	if md.Contributors != nil {
		data["contributors"] = md.Contributors
	}
	if md.Description != "" {
		data["description"] = md.Description
	}
	if md.DownloadPath != "" {
		data["downloadPath"] = md.DownloadPath
	}
	if md.HomePath != "" {
		data["homePath"] = md.HomePath
	}
	if md.Identifier != "" {
		data["identifier"] = md.Identifier
	}
	if md.Keywords != nil {
		data["keywords"] = md.Keywords
	}
	if md.Language != nil {
		data["language"] = md.Language
	}
	if md.License != nil {
		data["license"] = md.License
	}
	if md.ReadmePath != "" {
		data["readmePath"] = md.ReadmePath
	}
	if md.Theme != nil {
		data["theme"] = md.Theme
	}
	if md.Title != "" {
		data["title"] = md.Title
	}
	if md.AccrualPeriodicity != "" {
		data["accrualPeriodicity"] = md.AccrualPeriodicity
	}
	if md.Version != "" {
		data["version"] = md.Version
	}

	return json.Marshal(data)
}

Steps to complete:

  • create and push a WIP PR
  • Implement func (q *Transform) MarshalJSONObject() ([]byte, error){}
  • Update func (q *Transform) MarshalJSON(data []byte) error to call MarshalJSONObject()
  • Implement func (v *VisConfig) MarshalJSONObject() ([]byte, error){}
  • Update func (v *VisConfig) MarshalJSON(data []byte) error to call MarshalJSONObject()
  • Implement func (s Structure) MarshalJSONObject() ([]byte, error){}
  • Update func (s Structure) MarshalJSON(data []byte) error to call MarshalJSONObject()
  • Implement func (cm *Commit) MarshalJSONObject() ([]byte, error){}
  • Update func (cm *Commit) MarshalJSON(data []byte) error to call MarshalJSONObject()