3

I have an array that looks like:

 $items = @("Title    : 123456 
 field_1  : User One 
 field_2  : User 
 field_3  : One 
 field_4  : 26 
 field_5  : J123456")

However, I need the values to be in a hashtable for it to be accepted by the add-pnplistitem command. How do I convert this table into a Hashtable and be accepted by the PNP powershell command?

Thank you in advance!

1
  • 5
    That's an array with a multi-line string as only element, are you sure this is what you have? and if so, why you have it like this? Commented Jun 26, 2022 at 14:48

3 Answers 3

5

Sage Pourpre's helpful answer shows how to parse your multiline string line by line into an ordered hashtable (dictionary, of type [ordered]), which preserves the input order, i.e. the order of the key-property values encountered in the input string.

A simpler alternative that does not preserve the input order, however,[1] is to use the ConvertFrom-StringData cmdlet, which requires replacing the : separators in your input with = in order to make the cmdlet recognize the input lines as key-value pairs:

$items = @("Title    : 123456 
 field_1  : User One 
 field_2  : User 
 field_3  : One 
 field_4  : 26 
 field_5  : J123456")

ConvertFrom-StringData ($items -join "`n" -replace ':', '=')

Note:

  • -join "`n" joins the elements of the array with newlines to form a single, multiline string to pass to ConvertFrom-StringData; in your case, given that there's only one element, that one element (which is a multiline string itself) is returned as-is.

  • As zett42 points, out, ConvertFrom-StringData treats \ as the escape character, so if verbatim \ are in your input, you'd have to double them first, with -replace '\\', '\\' (sic).

Resulting output (a [hashtable], with inherently unordered entries):[1]

Name                           Value
----                           -----
field_3                        One
field_4                        26
field_2                        User
Title                          123456
field_1                        User One
field_5                        J123456

[1] GitHub issue #19070 is a feature request to make ConvertFrom-String data output a dictionary type that does preserve the input ordering, using a type derived from [hashtable] so as to preserve backward compatibility, something that has already been successfully implemented in the v7.3+ in the ConvertFrom-Json cmdlet via its -AsHashtable switch. Unfortunately, as of this writing (v7.5.x), the feature request is languishing.

Sign up to request clarification or add additional context in comments.

Comments

4

You don't have an array of elements, what you have is a single string within an array. All those elements are parts of the same item.

Therefore, you need to split the string into lines, then into their delimiter, remove the trailing spaces and build your hashtable.

# This is an array containing 1 string.
$items = @("Title    : 123456 
 field_1  : User One 
 field_2  : User 
 field_3  : One 
 field_4  : 26 
 field_5  : J123456")

# Note, I used the Ordered keyword. This is only needed if you want to # 
# preserve the order of the elements within your original string
$MyHashtable = [Ordered]@{}
$items -split "`r?`n" | ForEach-Object { 
    $el = $_.split(':') 
    $Key = $el[0].Trim()
    $MyHashtable.$key = $el[1].trim()
}

# Output your hashtable
$MyHashtable

Comments

0

the code below seems well enuf commented, but please feel free to ask if i failed to make things clear enuf.


# the example array holds ONE item = a multiline string
$OneItemInArray = @("Title    : 123456 
 field_1  : User One 
 field_2  : User 
 field_3  : One 
 field_4  : 26 
 field_5  : J123456")

# the PNP docs say that the `-Values` parameter requires a hashtable
#    but it does not mention an [ORDERED] one
#
# if you NEED the items in the input order,
#    swap the comment marker in the next two lines
$PnpHashtable = @{}
#$PnpHashtable = [ordered]@{}

# using the system newline allows skipping the "cr -vs- cr\lf" problem
#
# since you have only ONE item in the array, there is no need to iterate thru it
$OneItemInArray[0] -split [System.Environment]::NewLine |
    ForEach-Object {
        # the `-split` operator accepts regex
        #    the `.Split()` method does not
        #
        # the `.Trim()` method defaults to trimming leading and trailing <white-space> chars
        #
        # you can assign multiple values to a list of $Vars
        $Name, $Value = $_.Trim() -split '\s+:\s+' 
        #
        # doing a single `Add()` is easier to read for me
        $PnpHashtable.Add($Name, $Value)
        }

'=' * 20
$PnpHashtable
'=' * 20

the output for the NON-ordered hashtable ...

====================
Name                           Value                                                                                                                                                                                                
----                           -----                                                                                                                                                                                                
field_3                        One                                                                                                                                                                                                  
field_4                        26                                                                                                                                                                                                   
field_1                        User One                                                                                                                                                                                             
field_2                        User                                                                                                                                                                                                 
field_5                        J123456                                                                                                                                                                                              
Title                          123456                                                                                                                                                                                               
====================

Comments

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.