0

I have an object converted from JSON which contains information about 'Trusted clients'. There are two properties one of which identifies the uniqueness of a client: Name AND Thumbprint, so if there are elements, either contain the same Name or Thumbprint, they must be omitted.

Also, I'd like to point that output array should contain additional property - Id which could be generated with - New-Guid. That particular case was discussed here: enter link description here.

{
  "TrustedClients": [
        {
            "Name": "Client1",
            "Thumbprint": "5ed7eb688e404bd787585637975ddb01",
            "CallbackThumbprint": "b7f610106fa24afe9460ab8e4f2db1fc"
        },
        {
            "Name": "Client2",
            "Thumbprint": "5ed7eb688e404bd787585637975ddb01",
            "CallbackThumbprint": "b7f610106fa24afe9460ab8e4f2db1fc"
        },
        {
            "Name": "Client3",
            "Thumbprint": "1700a8497495d6053be04b690b98479fd62e6cc9",
            "CallbackThumbprint": "b7f610106fa24afe9460ab8e4f2db1fc"
        }
    ]
}

Is there an efficient way to get an array of unique objects specified by Name AND Thumbprint properties? So in that case the output array should contain only one object with name Client3 since there are two elements with the same Thumbprint value:

{
  "TrustedClients": [
        {
            "Id": "{(New-Guid).ToString()}"
            "Name": "Client3",
            "Thumbprint": "1700a8497495d6053be04b690b98479fd62e6cc9",
            "CallbackThumbprint": "b7f610106fa24afe9460ab8e4f2db1fc"
        }
    ]
}

I was tweaking with grouping at first, but it conflicts with the basic idea - uniqueness by Name AND Thumbprint. It's became obvious that grouping elements by Name AND Thumbprint potentially could return array with different Name values, but the same Thumbprint and vice versa.

6
  • 2
    "It's became obvious that grouping elements by Name AND Thumbprint potentially could return array with different Name values, but the same Thumbprint and vice versa." - I fail to see how that is at all obvious. Does $jsonObject.TrustedClients |Group-Object Name,Thumbprint group objects with different Name values together? If so, that's a bug. Commented Dec 24, 2021 at 17:15
  • May be I miss something, but $jsonObject.TrustedClients |Group-Object Name,Thumbprint returns the same array. It's obvious for me that when something are grouped by specifying keys the values of keys itself must be unique. In that particular case, since there are two equal Thumbprint with the same Name, grouping returns two different objects with different Names but same Thumbprint Commented Dec 24, 2021 at 17:26
  • Did you forget to post (part of) the input data? There are no two objects with the same Name property in the JSON you've posted. Commented Dec 24, 2021 at 17:28
  • Sorry, I got what you mean, I believe so. 'It's became obvious that grouping elements by Name AND Thumbprint potentially could return array with different Name values': of course that is not a way to get a unique collection of objects. I've meant that by grouping in that case by Name and Thumbprint is a wrong way to get a desired result. So what I want is to get a unique array of objects where Name and Thumbprint values don't repeat in any object of an array Commented Dec 24, 2021 at 17:33
  • Based on the data you've shown, isn't grouping on Thumbprint sufficient then? How do you want to handle the conflicting names? Should the result of merging the first two entries (based on their common thumbprint value 5ed7eb688e404bd787585637975ddb01) have the Name "Client1" or "Client2" (or something else completely)? Commented Dec 24, 2021 at 17:57

1 Answer 1

1

The way I see around it, is to Group-Object 2 times, on Name and on Thumbprint, to get those objects that are duplicated, once we have this information we can skip them by filtering the object[].

I'm using -NoElement in this case for efficiency.

Since I'm a total noob with classes I decided to make one for practicing purposes :)

class UniqueJSON {
    [object[]]$Items

    UniqueJSON ([pscustomobject[]]$In) {
        $this.Items = $In
        $this.SetGuid()
    }

    [void]SetGuid () {
        $this.Items.Where({ -not $_.ID }).ForEach({
            $_.PSObject.Properties.Add([psnoteproperty]::new(
                    'ID', [guid]::NewGuid().Guid
                )
            )
        })
    }

    [object[]]GetUnique() {
        $thumbNotShow = $this.Items | Group-Object Thumbprint -NoElement |
        Where-Object Count -GT 1
        $nameNotShow = $this.Items | Group-Object Name -NoElement |
        Where-Object Count -GT 1

        return $this.Items.Where({
            $_.Name -notin $nameNotShow.Name -and
            $_.Thumbprint -notin $thumbNotShow.Name
        })
    }
}

# Here you can import your JSON
$json = ..... | ConvertFrom-Json

# Now store the TrustedClients property in a variable
$trusted = $json.TrustedClients

# Create a new instance of the class
$instance = [UniqueJSON]$trusted

# Get the unique results
$instance.GetUnique()
  • $instance.GetUnique() returns:
Name    Thumbprint                               CallbackThumbprint               ID
----    ----------                               ------------------               --
Client3 1700a8497495d6053be04b690b98479fd62e6cc9 b7f610106fa24afe9460ab8e4f2db1fc 85af5623-365c-4f8a-9863-be38860406da
Sign up to request clarification or add additional context in comments.

2 Comments

Thanks, good trick with Thumbprint key. Generally it works for me with minor changes in code.
@yemo I have updated this answer, the code I provided before would fail on certain occasions

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.