Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Question] Is it possible to serialize alphabetically? #46

Closed
TMaddox opened this issue Oct 7, 2019 · 11 comments
Closed

[Question] Is it possible to serialize alphabetically? #46

TMaddox opened this issue Oct 7, 2019 · 11 comments

Comments

@TMaddox
Copy link

TMaddox commented Oct 7, 2019

I want to serialize alphabetically, including the discriminator, is this possible?

My class: (note I called my discriminator: "serializer")

    [CborDiscriminator("atom" , Policy = CborDiscriminatorPolicy.Always)]
    public class Atom
    {
        public int Z  { get; set; }
        public int A  { get; set; }
    }

This should serialize to:
{"A": 10, "serializer": "atom", "Z": 10}

Is this possible?

Edit: I need this because I need the hash of the cbor byte[] to match implementations in other languages

@mcatanzariti
Copy link
Member

Hi,

It would be possible to sort the member mappings during the object mapping initialization just after having call AutoMap.

However, in the current implementation, the discriminator is not materialized as an member mapping but is always serialized as the first property into the Cbor object...

@TMaddox
Copy link
Author

TMaddox commented Oct 8, 2019

Any idea how I can archive this? I would really need this to calculate the correct hash.

@jonassix
Copy link

Hi mcatanzariti,

Could you guide us in the right direction? Look at this example.

               {
                  "particle":{
                     "bytes":h                     '015757CDD6C17B409113E2979D58F611832103D0E2ACE56D2F8E15AAA285C57BBA9C0184D54CDD781B5637675704B5D1EA2BD800000010CCF4BD45FA4E2CDA8673BD45BF721878C05D57102856663EDA2160BF0B2FD83BF7A2B6D1ED6093B1CF769AFDD5EA1688',
                     "destinations":[
                        h                        '0217D072D6C4BC39D778FABC352ABBC3B4',
                        h                        '027BE4CA91F62F11794CCF66A92B771406'
                     ],
                     "from":h                     '040202385C29EF952488C05C6E44563CB73CBB163BEE9136E4366EF5AF2560B8CA05BE5F1F84C0',
                     "metaData":{
                        "application":"message"
                     },
                     "nonce":5275583715703691872,
                     "serializer":"radix.particles.message",
                     "to":h                     '0402023B2DC2EAA3A237C9AB13E3EC0357679DB51EFB63A7DC95980AD81A90D9B0EBD30C695A1B',
                     "version":100
                  },
                  "serializer":"radix.spun_particle",
                  "spin":1,
                  "version":100
               }

This is a payload we need to be able to generate and then create a hash of it. As a consequence correct sequence of properties is really important for us.
As you can see here, the properties are sorted alphabetically. Including the discriminator which is the property "serializer".

Any idea how we can achive this?

@TMaddox
Copy link
Author

TMaddox commented Oct 16, 2019

Could you please let us know if you are going to implement this or not and if you are going to, can you give us an ETA?

@mcatanzariti
Copy link
Member

Hi Maddox,

I have no simple solution right now.
The discriminator is not an actual property. It's added on the spot as the first property when the framework detect a polymorphic object.

A bad and slow workaround could be to serialize your class in a temporary cbor buffer. Then to deserialize it into a CborObject. Then sort the CborObject properties and serialize it again in the destination Cbor buffer

@TMaddox
Copy link
Author

TMaddox commented Oct 17, 2019

This would only work if I haven't got nested objects, wouldn't it? Only the top-level object would be sorted?

@mcatanzariti
Copy link
Member

You would have to recursively sort CborObject within CborObject

@TMaddox
Copy link
Author

TMaddox commented Oct 18, 2019

I tried that, but for example a CborValueType.Array doesn't have any public properties exposing the value, so I can't sort it. Any suggestions?

Edit: After further investigation, I think that the only types which I am able to sort recursively are CborValueType.Object. All others don't expose the value publicly (right now, I think the only one I would need to expose it is CborValueType.Array, as it holds other CborValueType.Object in my case)

@mcatanzariti
Copy link
Member

If the type is array, you can cast it to CborArray and iterate directly this class.

@TMaddox
Copy link
Author

TMaddox commented Oct 19, 2019

I managed to sort it now, I'll leave this issue open and hope you will implement it, because the solution right now is, as you said, a bad and slow workaround.

Thanks for the help!

@mcatanzariti
Copy link
Member

Release 1.6.0 brings the possibility to sort a type members alphabetically including the type discriminator.

Beware of several breaking changes listed in 1.6.0 release notes

    public class Issue0046
    {
        [CborDiscriminator("atom", Policy = CborDiscriminatorPolicy.Always)]
        public class Atom
        {
            public int Z { get; set; }
            public int A { get; set; }
        }

        [Fact]
        public void Test()
        {
            CborOptions options = new CborOptions();
            options.Registry.DiscriminatorConventionRegistry.RegisterConvention(new AttributeBasedDiscriminatorConvention<string>(options.Registry, "serializer"));
            options.Registry.ObjectMappingRegistry.Register<Atom>(objectMapping =>
            {
                objectMapping.AutoMap();
                objectMapping.SetOrderBy(m => m.MemberName);
            });

            Atom obj = new Atom
            {
                A = 10,
                Z = 10
            };

            const string hexBuffer = "A361410A6A73657269616C697A65726461746F6D615A0A";
            Helper.TestWrite(obj, hexBuffer, null, options);
        }
    }

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants