-2

When I use REST API to get the result, after getting part of the returned body, I got multiple items, and I have to loop the value under the item:

My return json ChangesInfoJson is:

[
    {
        "item":  {
                     "objectId":  "dd6d17aa11bexxxx110aeedb",
                     "originalObjectId":  "98a11c2fe8xxxx33a089fc62e986",
                     "gitObjectType":  "blob",
                     "commitId":  "a73b19232650xxxx1b6d4a6c969",
                     "path":  "/pipeline/PL_xxxx_START.json",
                     "url":  "https://dev.azure.com/xxxx"
                 },
        "changeType":  "edit"
    },
    {
        "item":  {
                     "objectId":  "13e6685cdxxxx485968d9e159",
                     "originalObjectId":  "48d0cf8xxxx19a43064",
                     "gitObjectType":  "blob",
                     "commitId":  "a73b19232650fxxx4a6c969",
                     "path":  "/trigger/TRIGGER_xxxxx_WKLY.json",
                     "url":  "https://dev.azure.com/xxxx"
                 },
        "changeType":  "edit"
    }
]

Then I using following code to parse the $ChangesInfoJson:

$ChangesInfoJson | foreach {
   $_.psobject.properties | foreach {
      $_.value | foreach {
            $_.psobject.properties | foreach {
               if ($_.name -eq "path"){
                    write-host change file path is:$_.value
               }   
            }
      }
   }
}

But the result is:

"change file path is: string path=/pipeline/PL_xxxx.json.value"

What I want is change file path is: /pipeline/PL_xxxx.json.

How did I change my code? Please help.

Joy
  • 1,171
  • 9
  • 15
  • Does this answer your question?: [PowerShell JSON set value](https://stackoverflow.com/a/64849675/1701026) – iRon Apr 26 '23 at 11:20

1 Answers1

3

Instead of initiating several questions for the same (or at least very similar) question, try to understand the (already existing) answers. A good practice to come to a conclusion of a specific question is to:

  • create a Minimal, Reproducible Example (for this, take all the words of the concept literal)
  • Show what you receive as an actual result of your attempt to resolve the issue
  • Show what you would expect as a result to your question

(see also how to ask)

As for the question with a bounty, powershell parse Json file with \ and wildcard in the key name, it would only be fair to upvote or accepted the answers from the others instead of your own answer (which only covers a small part of the question).

Specific to this issue

(I actually suspect a bug here.)
For this I have taken the full Json example from your question powershell parse the Json after ConvertTo-Json

$Json = @' ...

{
  "id": "/subscriptions/fcxxxx7/resourceGroups/xxxxxx/providers/Microsoft.Web/sites/xxxx/workflows/Test_email",
  "name": "xxxxxxxxx/Test_email",
  "type": "Microsoft.Web/sites/workflows",
  "kind": "Stateful",
  "location": "East Asia",
  "properties": {
"files": {
  "Test_email/workflow.json": {
    "definition": {
      "$schema": "https://schema.management.azure.com/providers/Microsoft.Logic/schemas/2016-06-01/workflowdefinition.json#",
      "actions": {
        "Send_an_email_from_a_shared_mailbox_(V2)": {
          "inputs": {
            "host": {
              "connection": {
                "referenceName": "My new value for: TheValueIwant"
              }
            },
            "method": "post",
            "path": "/v2/SharedMailbox/Mail"
          },
          "runAfter": {},
          "type": "ApiConnection"
        }
      },
      "contentVersion": "1.0.0.0",
      "outputs": {}
    },
    "kind": "Stateful"
  }
}
  }
}
'@
$ChangeInfo = ConvertFrom-Json $Json

Once converted from json, using ConvertFrom-Json or implied by using Invoke-RestMethod, the result is a PowerShell object which is completely independent from (and unrelated to) Json. See also this answer from mklement0.

Accessing

Normally, Member-Access enumeration, offers you a convenient way to get the concerned values:

$ChangeInfo.changes.item.path

But in this specific case there appears to be a bug where the specific member name item is apparently internally used for the iteration. see: Can't enumerate item member #19570.
In other words, you will need to enumerate this specific member "manually":

$CommitInfo.changes.foreach{ $_.item }.path
/pipeline
/pipeline/PL_xxxx_START.json
/trigger
/trigger/TRIGGER_xxxx_WKLY.json

Filtering

This mean if yo want e.g filter a url of an item on a specific path you will need to do something like this:

$CommitInfo.changes.foreach{ $_.item }.where{ $_.path -eq '/pipeline/PL_xxxx_START.json' }.url
https://dev.azure.com/xxxx

And if you have multiple paths to filter on you might take advantage of this common comparison feature:

When the input is a collection, the operator returns the elements of the collection that match the right-hand value of the expression.

$PathFilter =
    '/pipeline/PL_xxxx_START.json',
    '/trigger/TRIGGER_xxxx_WKLY.json'
$CommitInfo.changes.foreach{ $_.item }.where{ $PathFilter -eq $_.path }.objectId
dd6d17aa11bexxxxx10aeedb
13e6685cddxxxxd9e159

Changing

To change a specific path within this concerned item property, e.g. the 3rd (the array is zero based):

$CommitInfo.changes.foreach{ $_.item }[2].path = 'Another path'
$CommitInfo |ConvertTo-Json -Depth 10

Results:

{
  "changeCounts": {
"Edit": 4
  },
  "changes": [
{
  "item": {
    "objectId": "7e852adxxxxxxxba3792",
    "originalObjectId": "c77692938423cxxxx912bf7",
    "gitObjectType": "tree",
    "commitId": "a73b19232650xxxxx1b6d4a6c969",
    "path": "/pipeline",
    "isFolder": true,
    "url": "https://dev.azure.com/xxxx"
  },
  "changeType": "edit"
},
{
  "item": {
    "objectId": "dd6d17aa11bexxxxx10aeedb",
    "originalObjectId": "98a11c2fe819xxxx089fc62e986",
    "gitObjectType": "blob",
    "commitId": "a73b19232650fcxxxxx6d4a6c969",
    "path": "/pipeline/PL_xxxx_START.json",
    "url": "https://dev.azure.com/xxxx"
  },
  "changeType": "edit"
},
{
  "item": {
    "objectId": "7b3cfd336cxxxxed652446",
    "originalObjectId": "a67b91d65xxxx9c4605143",
    "gitObjectType": "tree",
    "commitId": "a73b19232650fcbxxxx4a6c969",
    "path": "Another path",
    "isFolder": true,
    "url": "https://dev.azure.com/xxxx"
  },
  "changeType": "edit"
},
{
  "item": {
    "objectId": "13e6685cddxxxxd9e159",
    "originalObjectId": "48d0cf833xxxx43064",
    "gitObjectType": "blob",
    "commitId": "a73b19232xxxx6d4a6c969",
    "path": "/trigger/TRIGGER_xxxx_WKLY.json",
    "url": "https://dev.azure.com/xxxx"
  },
  "changeType": "edit"
}
  ]
}
iRon
  • 20,463
  • 10
  • 53
  • 79
  • First of all I know how to ask an effective question, the reason I keep revising the question is because my original question is more complex and may not be understood by many people. I'm constantly testing and simplifying questions, so I'm changing and narrowing down questions, and I'll delete old ones after submitting new ones. – Joy Apr 27 '23 at 02:10
  • https://stackoverflow.com/questions/76071906/powershell-parse-json-file-with-and-wildcard-in-the-key-name/76105017#76105017 This problem and the current problem are not related to the same project, and the requirements and backgrounds are different. You cannot combine them. – Joy Apr 27 '23 at 02:13
  • For current question, the `$CommitInfo.changes.foreach{ $_.item }.path` like a magic, I could get the same result with you. But waht I need is to get each value of the path and filtered those folder path, I only need the path `/pipeline/PL_xxxx_START.json`, `/trigger/TRIGGER_xxxx_WKLY.json`. I do not need to change those path, I just need to filter those path one by one and then loop this path, could you please help how to get each value of the path instead of all the paths in the output. Thanks a lot. – Joy Apr 27 '23 at 02:16
  • I guess I have been a little pedantic in my answer, knowing that in the end it indeed appeared to concern a bug. Anyways, I have updated my answer with a **filtering** section. – iRon Apr 27 '23 at 17:52
  • 1
    Although the updated answer didn't directly solve my update question, but `where{ $PathFilter -eq $_.path }` inspired me a lot and I solved it now with your help. My optimized statement is `$path =$( $CommitInfo.changes.Where{ -not $_.item.isFolder }.foreach{ $_.item }.path)`, thank you very much for your help., – Joy Apr 28 '23 at 10:13