yung peso
yung peso

Reputation: 1796

How to filter JSON data based off an empty field?

I'm calling an API and trying to parse the body response to filter out data. I've created a conditional for-loop to go through each object and check whether this field: Relationships.CurrentConfigurationVersion.Data is empty.

Here is my first attempt:

func (s *Server) getEmptyWorkSpaces(w http.ResponseWriter, r *http.Request) {
    
    // omitted API calls for brevity

    // body holds the JSON response
    body, err := ioutil.ReadAll(resp.Body)

    // label my struct type as data
    var data WorkspacesJSON

    err = json.Unmarshal(body, data)
    if err != nil {
        panic(err)
    }

    var data2 []*WorkspacesJSON
    for _, v := range data.Data {
        if v.Relationships.CurrentConfigurationVersion.Data == " " {
            data2 = append(data2, v)
        }
    }
}

The error occurs in the conditional statement because I'm comparing a struct type to a string.

cannot convert "" (untyped string constant) to struct{ID string "json:"id""; Type string "json:"type""}


Attempt 2 After some searching around I tried another attempt from information I learned:

func (s *Server) getEmptyWorkSpaces(w http.ResponseWriter, r *http.Request) {
    
    // omitted API calls for brevity

    // body holds the JSON response
    body, err := ioutil.ReadAll(resp.Body)

    // label my struct type as data, this time attach []*
    var data []*WorkspacesJSON

    // added & in this new attempt
    err = json.Unmarshal(body, &data)
    if err != nil {
        panic(err)
    }

    var data2 []*WorkspacesJSON
    for _, v := range data.Data {
        if v.Relationships.CurrentConfigurationVersion.Data == " " {
            data2 = append(data2, v)
        }
    }
}

The compiler throw another error but this time targeting v.Relationships.CurrentConfigurationVersion.Data saying:

v.Relationships undefined (type *WorkspacesJSON has no field or method Relationships)compilerMissingFieldOrMethod I'm not sure why I'm getting this error because in my first attempt this was not a problem? Clearly I am not understanding this.

Here is my type struct: It's fairly long but the only field of important is Data.Relationships.CurrentConfigurationVersion.Data

type WorkspacesJSON struct {
    Data []struct {
        ID         string `json:"id"`
        Type       string `json:"type"`
        Attributes struct {
            AllowDestroyPlan           bool        `json:"allow-destroy-plan"`
            AutoApply                  bool        `json:"auto-apply"`
            AutoDestroyAt              interface{} `json:"auto-destroy-at"`
            CreatedAt                  time.Time   `json:"created-at"`
            Environment                string      `json:"environment"`
            Locked                     bool        `json:"locked"`
            Name                       string      `json:"name"`
            QueueAllRuns               bool        `json:"queue-all-runs"`
            SpeculativeEnabled         bool        `json:"speculative-enabled"`
            StructuredRunOutputEnabled bool        `json:"structured-run-output-enabled"`
            TerraformVersion           string      `json:"terraform-version"`
            WorkingDirectory           string      `json:"working-directory"`
            GlobalRemoteState          bool        `json:"global-remote-state"`
            UpdatedAt                  time.Time   `json:"updated-at"`
            ResourceCount              int         `json:"resource-count"`
            ApplyDurationAverage       int         `json:"apply-duration-average"`
            PlanDurationAverage        int         `json:"plan-duration-average"`
            PolicyCheckFailures        int         `json:"policy-check-failures"`
            RunFailures                int         `json:"run-failures"`
            WorkspaceKpisRunsCount     int         `json:"workspace-kpis-runs-count"`
            LatestChangeAt             time.Time   `json:"latest-change-at"`
            Operations                 bool        `json:"operations"`
            ExecutionMode              string      `json:"execution-mode"`
            VcsRepo                    struct {
                Branch            string `json:"branch"`
                IngressSubmodules bool   `json:"ingress-submodules"`
                Identifier        string `json:"identifier"`
                DisplayIdentifier string `json:"display-identifier"`
                OauthTokenID      string `json:"oauth-token-id"`
                WebhookURL        string `json:"webhook-url"`
                RepositoryHTTPURL string `json:"repository-http-url"`
                ServiceProvider   string `json:"service-provider"`
            } `json:"vcs-repo"`
            VcsRepoIdentifier string `json:"vcs-repo-identifier"`
            Permissions       struct {
                CanUpdate              bool `json:"can-update"`
                CanDestroy             bool `json:"can-destroy"`
                CanQueueDestroy        bool `json:"can-queue-destroy"`
                CanQueueRun            bool `json:"can-queue-run"`
                CanQueueApply          bool `json:"can-queue-apply"`
                CanReadStateVersions   bool `json:"can-read-state-versions"`
                CanCreateStateVersions bool `json:"can-create-state-versions"`
                CanReadVariable        bool `json:"can-read-variable"`
                CanUpdateVariable      bool `json:"can-update-variable"`
                CanLock                bool `json:"can-lock"`
                CanUnlock              bool `json:"can-unlock"`
                CanForceUnlock         bool `json:"can-force-unlock"`
                CanReadSettings        bool `json:"can-read-settings"`
                CanManageTags          bool `json:"can-manage-tags"`
            } `json:"permissions"`
            Actions struct {
                IsDestroyable bool `json:"is-destroyable"`
            } `json:"actions"`
            Description         interface{}   `json:"description"`
            FileTriggersEnabled bool          `json:"file-triggers-enabled"`
            TriggerPrefixes     []interface{} `json:"trigger-prefixes"`
            Source              string        `json:"source"`
            SourceName          interface{}   `json:"source-name"`
            SourceURL           interface{}   `json:"source-url"`
            TagNames            []interface{} `json:"tag-names"`
        } `json:"attributes"`
        Relationships struct {
            Organization struct {
                Data struct {
                    ID   string `json:"id"`
                    Type string `json:"type"`
                } `json:"data"`
            } `json:"organization"`
            CurrentRun struct {
                Data struct {
                    ID   string `json:"id"`
                    Type string `json:"type"`
                } `json:"data"`
                Links struct {
                    Related string `json:"related"`
                } `json:"links"`
            } `json:"current-run"`
            LatestRun struct {
                Data struct {
                    ID   string `json:"id"`
                    Type string `json:"type"`
                } `json:"data"`
                Links struct {
                    Related string `json:"related"`
                } `json:"links"`
            } `json:"latest-run"`
            Outputs struct {
                Data []interface{} `json:"data"`
            } `json:"outputs"`
            RemoteStateConsumers struct {
                Links struct {
                    Related string `json:"related"`
                } `json:"links"`
            } `json:"remote-state-consumers"`
            CurrentStateVersion struct {
                Data struct {
                    ID   string `json:"id"`
                    Type string `json:"type"`
                } `json:"data"`
                Links struct {
                    Related string `json:"related"`
                } `json:"links"`
            } `json:"current-state-version"`
            CurrentConfigurationVersion struct {
                Data struct {
                    ID   string `json:"id"`
                    Type string `json:"type"`
                } `json:"data"`
                Links struct {
                    Related string `json:"related"`
                } `json:"links"`
            } `json:"current-configuration-version"`
            AgentPool struct {
                Data interface{} `json:"data"`
            } `json:"agent-pool"`
            Readme struct {
                Data struct {
                    ID   string `json:"id"`
                    Type string `json:"type"`
                } `json:"data"`
            } `json:"readme"`
        } `json:"relationships"`
        Links struct {
            Self string `json:"self"`
        } `json:"links"`
    } `json:"data"`
    Links struct {
        Self  string      `json:"self"`
        First string      `json:"first"`
        Prev  interface{} `json:"prev"`
        Next  string      `json:"next"`
        Last  string      `json:"last"`
    } `json:"links"`
    Meta struct {
        StatusCounts struct {
            Pending            int `json:"pending"`
            PlanQueued         int `json:"plan-queued"`
            Planning           int `json:"planning"`
            Planned            int `json:"planned"`
            Confirmed          int `json:"confirmed"`
            ApplyQueued        int `json:"apply-queued"`
            Applying           int `json:"applying"`
            Applied            int `json:"applied"`
            Discarded          int `json:"discarded"`
            Errored            int `json:"errored"`
            Canceled           int `json:"canceled"`
            CostEstimating     int `json:"cost-estimating"`
            CostEstimated      int `json:"cost-estimated"`
            PolicyChecking     int `json:"policy-checking"`
            PolicyOverride     int `json:"policy-override"`
            PolicyChecked      int `json:"policy-checked"`
            PolicySoftFailed   int `json:"policy-soft-failed"`
            PlannedAndFinished int `json:"planned-and-finished"`
            PostPlanRunning    int `json:"post-plan-running"`
            PostPlanCompleted  int `json:"post-plan-completed"`
            PreApplyRunning    int `json:"pre-apply-running"`
            PreApplyCompleted  int `json:"pre-apply-completed"`
            Fetching           int `json:"fetching"`
            None               int `json:"none"`
            Total              int `json:"total"`
        } `json:"status-counts"`
        Pagination struct {
            CurrentPage int         `json:"current-page"`
            PageSize    int         `json:"page-size"`
            PrevPage    interface{} `json:"prev-page"`
            NextPage    int         `json:"next-page"`
            TotalPages  int         `json:"total-pages"`
            TotalCount  int         `json:"total-count"`
        } `json:"pagination"`
    } `json:"meta"`
}

I'm stuck in an eternal loop of those two same errors above, and trying to create hacky functions to get the job done, but no luck.

I'm very new to Go, I have experience with Python and working with JSON in Py is much easier for me but I want to try this using Go. Thanks in advance for your guidance.

How can I filter my JSON body using a conditional to check if a field is empty?

EDIT: In my second attempt, How would I be able to select the field I'm looking for, Relationships.CurrentConfigurationVersion.Data? Once I figure that out I think I will be okay. Currently its saying that WorkspaceJSON has no field of method forRelationships. This was not the case for my first attempt.

Upvotes: 1

Views: 651

Answers (1)

Amirreza Noori
Amirreza Noori

Reputation: 1525

There are lots of ways to check is struct empty or not, which is discussed here: How to check for an empty struct?

Also the append part of the code, must have the same type; as the following code:

data2 := WorkspacesJSON{}
for _, v := range data.Data {
    if fmt.Sprintf("%v", v.Relationships.CurrentConfigurationVersion.Data) == "{ }" {
        data2.Data = append(data2.Data, v)
    }
}

Upvotes: 1

Related Questions