Skip to content

ConvertTo-Json cmdlet hangs with -Depth 10 for object created using Get-Content #6388

Description

Steps to reproduce

echo "testline1" > test.txt
echo "testline2" >> test.txt

$textContent = Get-Content .\test.txt
$json=ConvertTo-Json -InputObject $textContent -Depth 10 

Expected behavior

ConvertTo-Json should not hang and it should display proper error or exception

Actual behavior

ConvertTo-Json cmdlet hangs

Environment data

> $PSVersionTable
Name                           Value                                                                                        
----                           -----                                                                                        
PSVersion                      5.1.16299.248                                                                                
PSEdition                      Desktop                                                                                      
PSCompatibleVersions           {1.0, 2.0, 3.0, 4.0...}                                                                      
BuildVersion                   10.0.16299.248                                                                               
CLRVersion                     4.0.30319.42000                                                                              
WSManStackVersion              3.0                                                                                          
PSRemotingProtocolVersion      2.3                                                                                          
SerializationVersion           1.1.0.1                                                                                      

Activity

  1. BrucePay commented on Mar 13, 2018

    @BrucePay
    Collaborator

    Hi ILAVELAN KANNIAPPAN (@ikanni) - I suspect it's not actually hanging - it's just descending very deeply into the object tree which takes a very, very long time. Just take a look at the output from:
    ConvertTo-Json -InputObject $textContent -Depth 3
    It's converting two PSObjects wrapping strings. These objects have a lot of extra metadata added by Get-Content:

    [
      {
        "value": "testline1",
        "PSPath": "C:\\Users\\brucepay.REDMOND\\AppData\\Local\\Temp\\test.txt",
        "PSParentPath": "C:\\Users\\brucepay.REDMOND\\AppData\\Local\\Temp",
        "PSChildName": "test.txt",
        "PSDrive": {
          "CurrentLocation": "Users\\brucepay.REDMOND\\AppData\\Local\\Temp",
          "Name": "C",
          "Provider": {
            "ImplementingType": "Microsoft.PowerShell.Commands.FileSystemProvider",
            "HelpFile": "System.Management.Automation.dll-Help.xml",
            "Name": "FileSystem",
            "PSSnapIn": "Microsoft.PowerShell.Core",
            "ModuleName": "Microsoft.PowerShell.Core",
            "Module": null,
            "Description": "",
            "Capabilities": 52,
            "Home": "C:\\Users\\brucepay.REDMOND",
            "Drives": "C D E",
            "VolumeSeparatedByColon": true
          },
          "Root": "C:\\",
          "Description": "Windows",
          "MaximumSize": null,
          "Credential": {
            "UserName": null,
            "Password": null
          },
          :
          :
    

    Each additional level of depth will introduce more fields that will then need to be serialized. To get to depth 10, you'll be nesting very deeply into the object tree and it will seem to hang. If you call Get-Content with the -Raw flag, your example completes immediately:

    $textContent = Get-Content .\test.txt -Raw
    $json=ConvertTo-Json -InputObject $textContent -Depth 10
    

    Using -Raw tells Get-Content to not add all of the extra metadata, reducing the amount of work that needs to be done to serialize the objects.

  2. SteveL-MSFT commented on Mar 14, 2018

    @SteveL-MSFT
    Member

    Agree with Bruce Payette (@BrucePay) that the cmdlet is doing what it is supposed to. Perhaps Get-Content should be returning an array of strings and not objects (separate issue).

    The actual bug is that ConvertTo-Json doesn't implement StopProcessing() to Ctrl+C doesn't break out.

  3. daxian-dbw commented on Mar 14, 2018

    @daxian-dbw
    Member

    Perhaps Get-Content should be returning an array of strings and not objects (separate issue).

    Get-Content does return an array of strings, but it adds several NoteProperties to the string, including PSDrive and PSProvider that point to objects.

    > $s | gm
    
       TypeName: System.String
    
    Name             MemberType            Definition
    ----             ----------            ----------
    Clone            Method                System.Object Clone(), System.Object ICloneable.Clone()
    ...
    PSChildName      NoteProperty          string PSChildName=test.txt
    PSDrive          NoteProperty          PSDriveInfo PSDrive=F
    PSParentPath     NoteProperty          string PSParentPath=F:\
    PSPath           NoteProperty          string PSPath=F:\test.txt
    PSProvider       NoteProperty          ProviderInfo PSProvider=Microsoft.PowerShell.Core\FileSystem
    ReadCount        NoteProperty          long ReadCount=1
    
  4. BrucePay commented on Mar 14, 2018

    @BrucePay
    Collaborator

    Steve Lee (@SteveL-MSFT) Looking at the code, I don't think StopProcessing() is appropriate because the thread is not blocked. Adding checks to Stopping in the inner loops should be sufficient.

    Dongbo Wang (@daxian-dbw) Right - it would still return PSObjects but we could stop adding the extra metadata by default. This is a conceptually significant breaking change but in practice I don't think anyone would notice (except that Get-Content performance and memory foot print would suddenly improve.)

  5. BrucePay commented on Mar 14, 2018

    @BrucePay
    Collaborator

    Marked as a bug for the need to support Stopping in the cmdlet.

  6. ikanni commented on Mar 21, 2018

    @ikanni
    Author

    Dongbo Wang (@daxian-dbw) Bruce Payette (@BrucePay) Steve Lee (@SteveL-MSFT) Get-Content adds several NoteProperties, including PSDrive and PSProvider or extra metadata by default. Whether we will fix the Get-Content in future release to remove the several NoteProperties or extra metadata ? I understand it is breaking change.

  7. markekraus commented on Mar 21, 2018

    @markekraus
    Contributor

    ILAVELAN KANNIAPPAN (@ikanni) as a workaround you can do something like this:

    Get-Content C:\path\to\file.txt | %{$_.PSObject.BaseObject} | ConvertTo-Json

    I suggest opening a separate issue or locating an existing open issue and voting/commenting on it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Labels

Issue-BugIssue has been identified as a bug in the productResolution-FixedThe issue is fixed.WG-Cmdletsgeneral cmdlet issues

Type

No type

Projects

No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions