From 9eeee795e0ef2331cd28b435b716d572c5ec5303 Mon Sep 17 00:00:00 2001 From: Gabriel Adrian Samfira Date: Sun, 15 Dec 2024 00:08:41 +0200 Subject: [PATCH 1/2] Fix serialization of PSCustomObject wrapped object With the switch away from converting PSCustomObjects to dictionaries we broke the way values that are wrapped in a PSCustomObject are serialized. This is evident when values of hashtables are generated using Write-Output which generates a PSCustomObject (Which is not evident in powershell, as there is a lot of magic in powershell), but is clearly evident when we try to use an object generated in PowerShell, in C#. This change looks at the nested type of a PSCustomObject, and unwraps it if it's not just another PSCustomObject. Fixes: #157 Signed-off-by: Gabriel Adrian Samfira --- Tests/powershell-yaml.Tests.ps1 | 15 +++++++++++++++ lib/net47/PowerShellYamlSerializer.dll | Bin 10240 -> 10240 bytes .../PowerShellYamlSerializer.dll | Bin 10240 -> 10240 bytes src/PowerShellYamlSerializer.cs | 12 +++++++++++- 4 files changed, 26 insertions(+), 1 deletion(-) diff --git a/Tests/powershell-yaml.Tests.ps1 b/Tests/powershell-yaml.Tests.ps1 index db55a59..0c21647 100644 --- a/Tests/powershell-yaml.Tests.ps1 +++ b/Tests/powershell-yaml.Tests.ps1 @@ -28,6 +28,21 @@ Import-Module $modulePath InModuleScope $moduleName { $compareStrictly = Get-EquivalencyOption -Comparator Equality + Describe "Test PSCustomObject wrapped values are serialized correctly" { + Context "Wrapped values" { + It "Should serialize correctly" { + $expectBigInt = [System.Numerics.BigInteger]::Parse("9999999999999999999999999999999999999999999999999") + $obj = [PSCustomObject]@{a = Write-Output 'string'; b = Write-Output 1; c = Write-Output @{nested = $true};d = [pscustomobject]$expectBigInt} + $asYaml = ConvertTo-Yaml $obj + $fromYaml = ConvertFrom-Yaml $asYaml + + Assert-Equivalent -Options $compareStrictly -Expected "string" -Actual $fromYaml["a"] + Assert-Equivalent -Options $compareStrictly -Expected 1 -Actual $fromYaml["b"] + Assert-Equivalent -Options $compareStrictly -Expected $expectBigInt -Actual $fromYaml["d"] + } + } + } + Describe "Test encode-decode symmetry." { Context "Simple-Items" { diff --git a/lib/net47/PowerShellYamlSerializer.dll b/lib/net47/PowerShellYamlSerializer.dll index 5adca39adcbc88513b95c9736b3a7fdb21fff8af..e0d04d917597a02dc132a403cb69d8ebd771a70a 100644 GIT binary patch delta 2731 zcmZWr4QvzV8GhgI&UZd1apFq?A#sfJN1R{m{F^ig64ny7)v5SdGfHXVq=6AIAqhW= z!0s4nHUT3!QI;~KMJrNS$3zvi6HJI^65XGwHkGC>5~Hv&CRDKzZFHks$DTVohH7`Z z=X;;${rO(sec$K0#b8UOJnr`kdkA{?uTGUV}s%+wc%Qo*yH zAlhIQh)ScAOT`QM#<%#;l4eAk$68#1Y;>WRsAn+|8?&B9qeJLiW`xDZ>@nJ;suUNS zQRI?`JjRHW>v<1ZN~D0uk)lQlF;qPzMkFG6#WXy|1*w_$0dt~pZv@31sc}0kJ`8&> zSElTeD{EYGq!fND=z|8xJ{{EO15{=|?o3UPG^ecDBPH-Fkuu;4-@}IwuRD}VMTwMy zUy}waFhuewN)8Cb8D{%#`uN}E0Hs19`6>}%`ZE0z9mk07T~egV%u5GUNsB5n61*DR zw;bS5a;sHksa{=J(fL^H*=Dn8KLRRSr6rL7jEbP;kH(8dmOx55B;y9Dks32jTZq%u zrH)7~r0jqyaLSgZ|)G>EkW(>QJO@Ji#7t&CS0w}7h+ zrxN5=W395PWxt)M=n&B@j7K%t>xcGi-_w4$drwy(iB z27b-Bs+6MUU1c$<+0^rV-}{i>TYUqi$VRsl9Di=n_e+P`?(i zJ17W6r#4zA>og&oc-L<1vcH~xkYr57xUSfU4q|C%T5Q~8My*!T_bD%kzv*;_7t8|NH z)Q_#Z&~7;mSu8$bImN!<8?)G9?66&;oK7TI1??3TbSA-0(;-nwXA^9eMg=w;ZmF!A zxJ|>6&cnx)l>L{+5!@AtNodEaCmVRWu$M zGTKu|qFsEOL)6LVr7bi^ZqY^Cc~tAC0pI|=N%PP`8{UHWfAWWP4)GtMrm9^>{B?T?&Cq`B&vY@$Pil8* zhO>l1zqZOfzy$L&%VqqKrs%Ioo}oIHd5$x+RCe(`T+E+IIee2ZOZoi3dhm?g3NC=R z)>2j=e;>EOR+M$Dah?{!bDU7Z9N_!5?OaLqwlS`wXk2<GMP66}iZD0{y0alPERZ}gM0-LE0*hZ^?U$*r1z&6@UF9RLG zFm3L)hByh+QR%SdHdoBcu){Ph%}_3lNH;BHHthln53^Y)CKb}K^g|2ZvG9h4eRP`s zMaSqZdY7K%D1VPH@H@tov#4c`KQ))H_3p6@z#sWPcw3o^>(MdC4OlGJpFmRl#NhNy z?;O`yfvLC+W%M;VK;Psjy}<|Q=eT~$(+%l2?2G$)hqktM4fck*ztI~WqK@@#!-GSS zokn`j;nc|Pt?j#d2Zp=)w+~I9$jRW0SO5E`joO{`r++m1)10rQO>Q`% zx|l#lZ}75RvU>$4`i|bN!ob}3;}H+y`ncX6=by`p9y<~jPwMRs^mRr+(fhnMB)W4l z{ARcrs4@%3js&;VzWSTk{kVbjg4j#FG-5- zPf->o(!EI=MUyu2AKAuSp1*Vw-3cL7FWN%m=9s0&rp&Q8!F?DFzx%SUvA3on5a_ON zsH^kW^>q6K!Jel2n%btu-WQt!J>hV$x3Lyl(8$i;f&cn@rwbOXK{#+&&?8J(|vSpLgTCPLqx_-N(c+m}uoxAJ$?B*dsAA)2K( z^&AX1=4O9#a&mLp^2BGJS-Rb{z2gOoM01NV>G{L7)4N9sHBv9tPy+>Uc2hm9I-Gu7 vJ>Y(*L0C=j)L^eSks1FY#sJhX&LDUrJn^{T^!r6YA)afQb`{^_ali6E3VjA5 delta 2574 zcmZWr4RBOf75>hBZ{PkTvm`G+&Ce#;WJB0wllYc|O}1=lOj0F5OER>yR4{D*paZy& z6eSZRn_@d;2`2JdNA_lAmA1y$ZK2e^Nxe>@@ zzI!?FkSrIqavd!ZXMOTX+EaLp-RfA$L%@OlN}%8#fMmR^Np=a7g0fHinJn3+)n)wB zb|G7T!jhv}QSn~pMxq?>WH=KQJk_;}Q4P@Rw#t8N1@bpqfLC(V?bTC;6ejpAp2T7X zBe8_>-l5sq*-IXy)-V!5=I?34)yh%KPy@15rUa+2{+E%SF@hJ{M(L3^qLRK>N==?RD z2}{}Bb2igi=1GKE$_qQSqQn-pR%m)~DbF>XL!8-O<{oZfmQ>4Y?47Dyt5%R`Oq-V} zVJ!<0C5$#PYI>qssq_B-Ps;eLNfZy}H(arIiCx#yX(xzc`O&d+XMXWu%2C*FO9M%G# zeYm5Y=g%=eC$pVP3h!s8T8S5)al^@91{rqg^g{^;CJ? zuewaU&220=zLn@@lyvd!p)dtvkArIQ|`s# zt5k(IwSN-fknKkpJx7fc!! zv$1&=lG&aILJ^UHYqoZUf_jVaqMCa;Q}1V8K}m(`L$9M`Z}ivsNlc^bThLtqZv^s>GuC6%e%bv{YboO1lXv!Iu zhcidV*3lJOjc$5b+klJki8$i)n0qT8XWW5lTxY$TCXFv+g0I`ttV|jPE}(^`@I31V z#_1X7_mGRP8L#ncL%7f41Xo+k_-oq0{+sk$oM8X&xaL*YMNCuBeHpJ)t}t+B%r0@A zi++G#Q8oPsNAWLSa0ZQZ6Bp=)YZh+$3h8tU|J5?+BAwE*=(>HgZ}F;9D&%aHt<+ID z#}SSV<31v~?P}$FH)*Wpx;Gr_sTRu|qtuvI&KvtFhB1|Hx1}h3Wc-{2I`ARm5gU)% zc$~2w8AytHeoFQ+7UM<60Hzs3_=K?mg<3t9ql&Q&4UDU7eGOw9zJL*}joV;E>$Bs& zblkTQd$hf_q`G8;<31eM&Y%d}wD)Z!QgOMBdr1{aY8BX|y

M8!y|q35W4_?8iyI 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 delta 2517 zcmZWr3v3kE6+QRO?96`X;vIkRXYE~k{aJgx?mAvDyS+!lO{o>O;KAFr}>dKa_^g6 z8=}tYop;Z<=iPbp=FQBed(u7MKdk@${NqngKkXMUwoSjZh595>jpN~UK%XoZ^>QoK zh&jJ}f({fNZi9W?&nV!)P$lp|0YGv?phflwi^6hHyhAbBsYN}%wq5Y)yJK=fD=s<6 z+(?xJZjYI&;4ZpROlW`}-68*_70TagAs)$5uUF3)GMM7CxKmXOMyiJK?y;q%rMKNi zy~lW^>AW@@~Goa05s69a>T9iyTA}cjQw=tauLSd>LjcrfjZdn`H*vsYaIa z8%?b^HLAu6O%LD2ecc0NoY@(0jW;n%tKoI_OjWK!D@?_+=Cw-L!a}nWCR!LZJ=Lnz z761RI<#Uee@&ucz(gv4K2_Q1=QOnP_)vb-MvP1cvqm0_5Vbs!>WQ=jW{ECsFc6rQb zzo*>^gbo06+z+`p-n@J4v2Q*)uGTci0-VI!Lz_{U%bc~)eGhHg$bFdk>(Xb|6s>2* zCjt*ffE%we-x;7?_L@JYKguOD>T=_{qt9vJKDo}hz1rtG>-6G^vs*WC4xhq6uPg3! zqs-Pj(XD$iqs#NoQ>FW$^J$6O&mF)%-i*06JEoXC}CLDjgZ{gVhkG;fj*8(jaU zX57HXRKU*vFjl}61^5AS880Fr-*gp~Mg(DJkY|Y}3ulZNv&j_}kv{jmk!In+OB8ei zk0^sHblX`5%Vx?Mr2s-Jtb@vtxWgGj$L-uCRpMcrK7&%DPgEnw&(rdB>kzhC=7e>K ze=gT%vxEE~JtFF`G0P(Onuwq`%Z_8GsK?eUyM%8Gb)N~QsjypJfxtNp(2(GrpkpWR zNR_xlm#=ts<;GbdyrU~U-}c1ihE=5$m)lp>X0vbFMKjL0JicmTax2}S2hmF}YyG&2 zfJh=q{jME&jByv{@d4|-G-G@V)4Xm^vNB^BxP(rc!LzIzn4<5QFCq_589(LMhQoCc zr@2}c;~Uh^{!i%*oM!)JuK5q=Rm@Yw^)AlR8e!nVq+Mc>i(bcXsGi=(EEajd1+>t| zxI~{gm*ArBkWRPondYIZbY9D$Mf+yo;!$N(#Mx?FiBdVo%^bUodx-a~tAp>|jIo7k z=@Z8`szB!FsafTZ7D$?8NVQbO?Z#-gpIQ{o@8u*2Wip3PstI+5}aZT zVV*I9TZ~Ouqcvb1Dj7S`$k=7;n;ARtRqWL|c^mB22JLt-8xKB${n|lWQoCd?$Afr5 zyMSVhYS(NeQgOMB2T2u5YZVyQp0n}1jqlp{D30UrIEt5f^}1+`o}d?KK`wbi54=u6 ze%oZ;Gpbj|ALtstnbfwreY{QGynWPL$AemY8GG;zn!t}}4}QY!Rj#q{_0@lN%F)98 z3m+D)rkuYVo<1`Ag_pWsJ9p)+zwO&SEAxu)&p+u1lCY9y4iP_d!wxrD>CF`qF2GFoML6SIm4X{Y&BX^Ju@7bekgI+C|nLYma=bxOMW3R|_I* zoia?}OCRy-L0G*exY!XZse^>3N^wn{C%{>9YR;hG+J~%7CI@`F#f;;_jDFPGl;O8@ z!%9zO#A$1jo2T-uV8seLc$~j5XM0S|ab{UBgU(kKbTa=;>0BijR{!$26INc%=LVd} z49HtHOj(txK;;UTe=2Ed)(q=$ZZVIsd>$*f5_8R!n1|nvWtTrzGsBY*LYP6G70+As zc~<&_>MOH6%)NZx|FdwiwRw2$Kw_X}q^U6$8y*}PX-UL}8b=0VLxV#D$ylr@Igl70 ziOWN!qx^MUKmXnLLESxqH^vmVIsOFBm8xx$In>VLZx;Bk1)}^1Co0R!LOG}UXV2Vw zY}kDLTghTeRf)^%+j3=p_WzM8{EUi&)8z%?aGSIO z|CK#~V+-EknD$^2t!TzD)?xq&ZY>x=6B-fY-!MNvBm8UOObkP;j<7>TgWLv?v|UZy ZtFgnJjW7Hzln~-n+k&t1CQZkT{{geG Date: Sun, 15 Dec 2024 10:50:47 +0200 Subject: [PATCH 2/2] Add IDictionary type converter Add a new type converter for IDictionary types which unwraps PScustomObjects before serializing. Signed-off-by: Gabriel Adrian Samfira --- Tests/powershell-yaml.Tests.ps1 | 33 +++++++++++++- lib/net47/PowerShellYamlSerializer.dll | Bin 10240 -> 10752 bytes .../PowerShellYamlSerializer.dll | Bin 10240 -> 10752 bytes src/PowerShellYamlSerializer.cs | 42 +++++++++++++++++- 4 files changed, 73 insertions(+), 2 deletions(-) diff --git a/Tests/powershell-yaml.Tests.ps1 b/Tests/powershell-yaml.Tests.ps1 index 0c21647..cd25f70 100644 --- a/Tests/powershell-yaml.Tests.ps1 +++ b/Tests/powershell-yaml.Tests.ps1 @@ -29,7 +29,7 @@ InModuleScope $moduleName { $compareStrictly = Get-EquivalencyOption -Comparator Equality Describe "Test PSCustomObject wrapped values are serialized correctly" { - Context "Wrapped values" { + Context "A PSCustomObject containing nested PSCustomObjects" { It "Should serialize correctly" { $expectBigInt = [System.Numerics.BigInteger]::Parse("9999999999999999999999999999999999999999999999999") $obj = [PSCustomObject]@{a = Write-Output 'string'; b = Write-Output 1; c = Write-Output @{nested = $true};d = [pscustomobject]$expectBigInt} @@ -41,6 +41,37 @@ InModuleScope $moduleName { Assert-Equivalent -Options $compareStrictly -Expected $expectBigInt -Actual $fromYaml["d"] } } + + Context "A hashtable containing nested PSCustomObjects" { + It "Should serialize correctly" { + $expectBigInt = [System.Numerics.BigInteger]::Parse("9999999999999999999999999999999999999999999999999") + $obj = @{a = Write-Output 'string'; b = Write-Output 1; c = Write-Output @{nested = $true};d = [pscustomobject]$expectBigInt} + $asYaml = ConvertTo-Yaml $obj + $fromYaml = ConvertFrom-Yaml $asYaml + + Assert-Equivalent -Options $compareStrictly -Expected "string" -Actual $fromYaml["a"] + Assert-Equivalent -Options $compareStrictly -Expected 1 -Actual $fromYaml["b"] + Assert-Equivalent -Options $compareStrictly -Expected $expectBigInt -Actual $fromYaml["d"] + } + } + + Context "A generic dictionary containing nested PSCustomObjects" { + It "Should serialize correctly" { + $expectBigInt = [System.Numerics.BigInteger]::Parse("9999999999999999999999999999999999999999999999999") + $obj = [System.Collections.Generic.Dictionary[string, object]]::new() + $obj["a"] = Write-Output 'string' + $obj["b"] = Write-Output 1 + $obj["c"] = Write-Output @{nested = $true} + $obj["d"] = [pscustomobject]$expectBigInt + + $asYaml = ConvertTo-Yaml $obj + $fromYaml = ConvertFrom-Yaml $asYaml + + Assert-Equivalent -Options $compareStrictly -Expected "string" -Actual $fromYaml["a"] + Assert-Equivalent -Options $compareStrictly -Expected 1 -Actual $fromYaml["b"] + Assert-Equivalent -Options $compareStrictly -Expected $expectBigInt -Actual $fromYaml["d"] + } + } } Describe "Test encode-decode symmetry." { diff --git a/lib/net47/PowerShellYamlSerializer.dll b/lib/net47/PowerShellYamlSerializer.dll index e0d04d917597a02dc132a403cb69d8ebd771a70a..57a32e72b3b767105190042cb7a53491cd2fbad8 100644 GIT binary patch delta 4385 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 Qaei>_h_CuHHry!w4TVV6^8f$< delta 3776 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 as IDictionary; + return deserializedObject; + } + + public void WriteYaml(IEmitter emitter, object value, Type type, ObjectSerializer serializer) { + var hObj = (IDictionary)value; + emitter.Emit(new MappingStart()); + foreach (DictionaryEntry entry in hObj) { + if(entry.Value == null) { + if (this.omitNullValues == true) { + continue; + } + serializer(entry.Key, entry.Key.GetType()); + emitter.Emit(new Scalar(AnchorName.Empty, "tag:yaml.org,2002:null", "", ScalarStyle.Plain, true, false)); + continue; + } + serializer(entry.Key, entry.Key.GetType()); + if (entry.Value is PSObject nestedObj) { + serializer(nestedObj.BaseObject, nestedObj.BaseObject.GetType()); + } else { + serializer(entry.Value, entry.Value.GetType()); + } + } + emitter.Emit(new MappingEnd()); + } +} + public class PSObjectTypeConverter : IYamlTypeConverter { private bool omitNullValues; @@ -70,7 +110,6 @@ public object ReadYaml(IParser parser, Type type, ObjectDeserializer rootDeseria public void WriteYaml(IEmitter emitter, object value, Type type, ObjectSerializer serializer) { var psObj = (PSObject)value; - emitter.Emit(new MappingStart()); foreach (var prop in psObj.Properties) { if (prop.Value == null) { @@ -161,6 +200,7 @@ public static SerializerBuilder BuildSerializer( builder = builder .WithEventEmitter(next => new StringQuotingEmitter(next)) .WithTypeConverter(new BigIntegerTypeConverter()) + .WithTypeConverter(new IDictionaryTypeConverter(omitNullValues)) .WithTypeConverter(new PSObjectTypeConverter(omitNullValues)); if (omitNullValues == true) { builder = builder