DHowett / go-plist

A pure Go Apple Property List transcoder
Other
416 stars 97 forks source link

Marshalling happens in reverse order. #52

Closed PrMinisterGR closed 4 years ago

PrMinisterGR commented 4 years ago

Hello. This is my data structure:

type FileVault2EnablePlist struct {
    FileVaultCredentials
    AdditionalUsers []FileVaultCredentials `plist:"AdditionalUsers,omitempty"`
}

type FileVaultCredentials struct {
    Username string `plist:"Username"`
    Password string `plist:"Password"`
}

This is the code that adds the data to it:

       rootUser := FileVaultCredentials{
        Username: supportUsername,
        Password: supportPassword,
    }

    additionalUser := FileVaultCredentials{
        Username: userToAddUsername,
        Password: userToAddPassword,
    }

    var additionalUsers []FileVaultCredentials
    additionalUsers = append(additionalUsers, additionalUser)

    usersToEnablePlist := &FileVault2EnablePlist{
        FileVaultCredentials: rootUser,
        AdditionalUsers:      additionalUsers,
    }

This is how I marshal it:

plistMacOS, err := plist.MarshalIndent(usersToEnablePlist, plist.XMLFormat, "\t")

When I print it, I get the plist with the data in the reverse order.

    fmt.Println("FileVaultEnablePlist:", string(plistMacOS))

<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
    <dict>
        <key>AdditionalUsers</key>
        <array>
            <dict>
                <key>Password</key>
                <string>standardUserPassword</string>
                <key>Username</key>
                <string>standardUser</string>
            </dict>
        </array>
        <key>Password</key>
        <string>supportPassword</string>
        <key>Username</key>
        <string>support</string>
    </dict>
</plist>

Hopefully I'm doing something obviously wrong.

Here is my data structure simply printed with Println:

fmt.Println("DEBUG PLIST:", usersToEnablePlist)
DEBUG PLIST: &{{support supportPassword} [{standardUser standardUserPassword}]}

Everything looks in the correct order in the data structure.

Reversing it from my data structure makes zero difference in the output.

type FileVault2EnablePlist struct {
    AdditionalUsers []FileVaultCredentials `plist:"AdditionalUsers,omitempty"`
    FileVaultCredentials
}
type FileVaultCredentials struct {
    Password string `plist:"Password"`
    Username string `plist:"Username"`
}

Println will correctly print the data structure elements in the reverse order:

fmt.Println("DEBUG PLIST:", usersToEnablePlist)
DEBUG PLIST: &{[{standardUserPassword standardUser}] {supportPassword support}}

Which makes no difference to Marshal:

<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
    <dict>
        <key>AdditionalUsers</key>
        <array>
            <dict>
                <key>Password</key>
                <string>standardUserPassword</string>
                <key>Username</key>
                <string>standardUser</string>
            </dict>
        </array>
        <key>Password</key>
        <string>supportPassword</string>
        <key>Username</key>
        <string>support</string>
    </dict>
</plist>

Thanks for the library, first of all. Do you have any ideas? Am I screwing up something?

Artoria2e5 commented 4 years ago

First of all you should not be concerned about this order, because cfDictionary is not supposed to be order-sensitive.

Now here is your answer. Before the plist generators write the dictionary, they sort it by key just so that the results are always the same no matter the order one assigned the dictionary. Now "p" goes before "u" in the alphabet, so "password" comes before "username".

https://github.com/DHowett/go-plist/blob/500bd5b9081b5957ac10389f86e069869f00c348/xml_generator.go#L100

PrMinisterGR commented 4 years ago

I guessed as much later. Thanks for the reply, it will be really useful for people using this for the first time with no previous plist experience :)

DHowett commented 4 years ago

Indeed! Thanks @Artoria2e5 for the answer. :smile: