Command work in Powershell 7, but not in Powershell 6 and 5.

Hello,

I wrote small script for extracting IP addresses from JSON file. File has structure like below:



<span style="font-size: 10pt">{
"origin": "aaa",
"category": "aaa",
"confidence": "aaa",
"name": "aaa",
"proto": "tcp",
"address": [
{
"cc": "PL",
"ip": "111.111.111.111",
"asn": 0000
}
],
"source": "aaa",
"time": "2020-02-25T07:17:21Z",
"dport": 80,
"sport": 54230,
"dip": "111.111.111.111",
"id": "xxx"
},
{
"origin": "sbbb",
"category": "bbb",
"confidence": "bbb",
"name": "bbb",
"proto": "tcp",
"address": [
{
"cc": "PL",
"ip": "222.222.222.222",
"asn": 000
}
],
"source": "aaa",
"time": "2020-02-25T07:17:11Z",
"dport": 80,
"sport": 44969,
"dip": "222.222.222.222",
"id": "xxx"
}</span>

<span style="font-size: 10pt">]</span>


For extracting IP addresses I use below command:

($JSON_file | ConvertFrom-Json | ForEach-Object address).ip | Out-File Only_IP_addresses.txt

And this command is working in PowerShell 7, but in PowerShell 6, and 5 it gives empty results… No errors, just empty results.

Any clue why is that?

I get “invalid json primitive” when I try it. You’re missing a square bracket in the beginning. You can also pretty the json with

($json_file | convertfrom-json) | convertto-json -depth 3 | set-content file.json

I assume $json_file comes from “get-content file.json”. For some reason, an extra set of parentheses are needed in ps 5 & 6, or else it thinks address is a method:

$JSON_file = get-content file.json
(($JSON_file | ConvertFrom-Json) | ForEach-Object address).ip | Out-File Only_IP_addresses.txt
$JSON_file | ConvertFrom-Json | ForEach-Object address

OverloadDefinitions
-------------------
System.Object&, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 Address(int )

The ConvertFrom-JSON cmdlet is different in PS7 - It has been improved.
However, your error is due to bad JSON formatting. What you posted above mangled 2 records together.
Here is the correct formatting:

$JSONCollection = @(
@'
{
    "origin": "aaa",
    "category": "aaa",
    "confidence": "aaa",
    "name": "aaa",
    "proto": "tcp",
    "address": [
        {
        "cc": "PL",
        "ip": "111.111.111.111",
        "asn": 0000
        }
    ],
    "source": "aaa",
    "time": "2020-02-25T07:17:21Z",
    "dport": 80,
    "sport": 54230,
    "dip": "111.111.111.111",
    "id": "xxx"
}
'@
@'
{
    "origin": "sbbb",
    "category": "bbb",
    "confidence": "bbb",
    "name": "bbb",
    "proto": "tcp",
    "address": [
        {
        "cc": "PL",
        "ip": "222.222.222.222",
        "asn": 000
        }
    ],
    "source": "aaa",
    "time": "2020-02-25T07:17:11Z",
    "dport": 80,
    "sport": 44969,
    "dip": "222.222.222.222",
    "id": "xxx"
}
'@
)

and the ConvertFrom-JSON in PS5 would work here as in:

$JSONCollection | ConvertFrom-Json | foreach address

cc ip              asn
-- --              ---
PL 111.111.111.111   0
PL 222.222.222.222   0

and

($JSONCollection | ConvertFrom-Json | foreach address).IP

111.111.111.111
222.222.222.222

@js: I added extra parenthesis and now it is working correctly.

@Sam Boutros: Indeed, this is that case, when PS 7 shows its advangage over previous PS editions.

Thank you all :slight_smile:

@Sam Boutros: that avoids the bug in PS 5/6 from processing the json line by line. I take his json file as this, formatted and with the missing square bracket at the top, and reading it in through get-content as an array of lines. Without the enclosing square brackets, it would error out. Address should be an array of one object, but in the pipeline for some reason it gets taken as a method.

[
    {
        "origin":  "aaa",
        "category":  "aaa",
        "confidence":  "aaa",
        "name":  "aaa",
        "proto":  "tcp",
        "address":  [
                        {
                            "cc":  "PL",
                            "ip":  "111.111.111.111",
                            "asn":  0
                        }
                    ],
        "source":  "aaa",
        "time":  "2020-02-25T07:17:21Z",
        "dport":  80,
        "sport":  54230,
        "dip":  "111.111.111.111",
        "id":  "xxx"
    },
    {
        "origin":  "sbbb",
        "category":  "bbb",
        "confidence":  "bbb",
        "name":  "bbb",
        "proto":  "tcp",
        "address":  [
                        {
                            "cc":  "PL",
                            "ip":  "222.222.222.222",
                            "asn":  0
                        }
                    ],
        "source":  "aaa",
        "time":  "2020-02-25T07:17:11Z",
        "dport":  80,
        "sport":  44969,
        "dip":  "222.222.222.222",
        "id":  "xxx"
    }
]
get-content file.json | convertfrom-json | get-member address


   TypeName: System.Object[]

Name    MemberType Definition
----    ---------- ----------
Address Method     System.Object&, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 Address(int )

[quote quote=205980]@Sam Boutros: that avoids the bug in PS 5/6 from processing the json line by line. I take his json file as this, formatted and with the missing square bracket at the top, and reading it in through get-content as an array of lines. Without the enclosing square brackets, it would error out. Address should be an array of one object, but in the pipeline for some reason it gets taken as a method.

PowerShell
42 lines
<textarea class="ace_text-input" wrap="off" autocorrect="off" autocapitalize="off" spellcheck="false" style="opacity: 0; height: 18px; width: 6.59771px; left: 51px; top: 0px;"></textarea>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
[
{
"origin": "aaa",
"category": "aaa",
"confidence": "aaa",
"name": "aaa",
"proto": "tcp",
"address": [
{
"cc": "PL",
"ip": "111.111.111.111",
"asn": 0
}
],
"source": "aaa",
"time": "2020-02-25T07:17:21Z",
"dport": 80,
"sport": 54230,
"dip": "111.111.111.111",
"id": "xxx"
},
{
"origin": "sbbb",
"category": "bbb",
"confidence": "bbb",
"name": "bbb",
"proto": "tcp",
"address": [
{
"cc": "PL",
"ip": "222.222.222.222",
"asn": 0
}
],
"source": "aaa",
"time": "2020-02-25T07:17:11Z",
"dport": 80,
"sport": 44969,
"dip": "222.222.222.222",
"id": "xxx"
}
]
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
PowerShell
8 lines
<textarea class="ace_text-input" wrap="off" autocorrect="off" autocapitalize="off" spellcheck="false" style="opacity: 0; height: 18px; width: 6.59771px; left: 44px; top: 0px;"></textarea>
1
2
3
4
5
6
7
8
get-content file.json | convertfrom-json | get-member | where name -eq address
TypeName: System.Object[]
Name MemberType Definition
---- ---------- ----------
Address Method System.Object&, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 Address(int )
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
[/quote]

As usual you are indeed correct my good friend. I simply went around the issue to produce the desired result in PS5 :slight_smile: