NancyFx / Nancy.Serialization.JsonNet

NewtonSoft.Json serializer for Nancy
MIT License
39 stars 32 forks source link

Enum mapping goes wrong #25

Closed LundinMichael closed 7 years ago

LundinMichael commented 8 years ago

I've noticed that, when using this.Bind<>(), I lose my enum values and some of them goes to default (0). In other cases I've noticed that the enum values change from the original request when i use this.Body<>(). For example I have enum "Dog = 1, Cat = 2, Horse = 3", my original request holds an object with enum values "1, 3" but when I bind, they turn to "3, 3" (Horse, horse).

khellang commented 8 years ago

Can you post your request body (JSON) and your DTO?

LundinMichael commented 8 years ago

DTO:

public enum ModelNiva
{
    Skiss = 1,
    Forenklad = 2,
    Standard = 3,
    Utokad = 4
}

JSON:

The enum value in this case that maps "wrong" when binding is the property "Ansokansniva: 2" and becomes a 4 (Utokad).

{
    "Id": 131663,
    "Version": 1,
    "AnsverId": 71539,
    "Budgetniva": 4,
    "StartDatum": "2015-10-14T22:00:00Z",
    "SlutDatum": "2016-10-06T22:00:00Z",
    "AddProjektparter": true,
    "AddFinansiarer": true,
    "Nivaskillnad": true,
    "Projektparter": [
        {
            "IregKey": "<key type='20' id='19935'/>",
            "IregId": 19935,
            "Koordinerande": true,
            "Organisationsnamn": "NETHOUSE DALARNA AKTIEBOLAG",
            "Arbetsplatsnamn": "NETHOUSE DALARNA AKTIEBOLAG",
            "Organisationsnummer": "556653-7444",
            "Kostnader": [
                {
                    "Id": 1,
                    "Kostnadsslag": "Personalkostnader",
                    "KostnaderPerAr": [
                        {
                            "Ar": 2015,
                            "Summa": 0,
                            "AndringsmarkeringarUtokad": null,
                            "AndringsmarkeringarStandard": null
                        },
                        {
                            "Ar": 2016,
                            "Summa": 0,
                            "AndringsmarkeringarUtokad": null,
                            "AndringsmarkeringarStandard": null
                        }
                    ]
                },
                {
                    "Id": 2,
                    "Kostnadsslag": "Utrustning, mark, byggnader",
                    "KostnaderPerAr": [
                        {
                            "Ar": 2015,
                            "Summa": 0,
                            "AndringsmarkeringarUtokad": null,
                            "AndringsmarkeringarStandard": null
                        },
                        {
                            "Ar": 2016,
                            "Summa": 0,
                            "AndringsmarkeringarUtokad": null,
                            "AndringsmarkeringarStandard": null
                        }
                    ]
                },
                {
                    "Id": 3,
                    "Kostnadsslag": "Konsultkostnader, licenser m.m",
                    "KostnaderPerAr": [
                        {
                            "Ar": 2015,
                            "Summa": 0,
                            "AndringsmarkeringarUtokad": null,
                            "AndringsmarkeringarStandard": null
                        },
                        {
                            "Ar": 2016,
                            "Summa": 0,
                            "AndringsmarkeringarUtokad": null,
                            "AndringsmarkeringarStandard": null
                        }
                    ]
                },
                {
                    "Id": 4,
                    "Kostnadsslag": "Övriga direkta kostnader inkl. resor",
                    "KostnaderPerAr": [
                        {
                            "Ar": 2015,
                            "Summa": 0,
                            "AndringsmarkeringarUtokad": null,
                            "AndringsmarkeringarStandard": null
                        },
                        {
                            "Ar": 2016,
                            "Summa": 0,
                            "AndringsmarkeringarUtokad": null,
                            "AndringsmarkeringarStandard": null
                        }
                    ]
                },
                {
                    "Id": 5,
                    "Kostnadsslag": "Indirekta kostnader",
                    "KostnaderPerAr": [
                        {
                            "Ar": 2015,
                            "Summa": 0,
                            "AndringsmarkeringarUtokad": null,
                            "AndringsmarkeringarStandard": null
                        },
                        {
                            "Ar": 2016,
                            "Summa": 0,
                            "AndringsmarkeringarUtokad": null,
                            "AndringsmarkeringarStandard": null
                        }
                    ]
                }
            ],
            "BidragPerAr": [],
            "Finansiarer": []
        },
        {
            "IregKey": "<key type='20' id='31453'/>",
            "IregId": 31453,
            "Koordinerande": false,
            "Organisationsnamn": "AFTONBLADET HIERTA AKTIEBOLAG",
            "Arbetsplatsnamn": "AFTONBLADET HIERTA AKTIEBOLAG",
            "Organisationsnummer": "556100-1123",
            "Kostnader": [
                {
                    "Id": 1,
                    "Kostnadsslag": "Personalkostnader",
                    "KostnaderPerAr": [
                        {
                            "Ar": 2015,
                            "Summa": 0,
                            "AndringsmarkeringarUtokad": null,
                            "AndringsmarkeringarStandard": null
                        },
                        {
                            "Ar": 2016,
                            "Summa": 0,
                            "AndringsmarkeringarUtokad": null,
                            "AndringsmarkeringarStandard": null
                        }
                    ]
                },
                {
                    "Id": 2,
                    "Kostnadsslag": "Utrustning, mark, byggnader",
                    "KostnaderPerAr": [
                        {
                            "Ar": 2015,
                            "Summa": 0,
                            "AndringsmarkeringarUtokad": null,
                            "AndringsmarkeringarStandard": null
                        },
                        {
                            "Ar": 2016,
                            "Summa": 0,
                            "AndringsmarkeringarUtokad": null,
                            "AndringsmarkeringarStandard": null
                        }
                    ]
                },
                {
                    "Id": 3,
                    "Kostnadsslag": "Konsultkostnader, licenser m.m",
                    "KostnaderPerAr": [
                        {
                            "Ar": 2015,
                            "Summa": 0,
                            "AndringsmarkeringarUtokad": null,
                            "AndringsmarkeringarStandard": null
                        },
                        {
                            "Ar": 2016,
                            "Summa": 0,
                            "AndringsmarkeringarUtokad": null,
                            "AndringsmarkeringarStandard": null
                        }
                    ]
                },
                {
                    "Id": 4,
                    "Kostnadsslag": "Övriga direkta kostnader inkl. resor",
                    "KostnaderPerAr": [
                        {
                            "Ar": 2015,
                            "Summa": 0,
                            "AndringsmarkeringarUtokad": null,
                            "AndringsmarkeringarStandard": null
                        },
                        {
                            "Ar": 2016,
                            "Summa": 0,
                            "AndringsmarkeringarUtokad": null,
                            "AndringsmarkeringarStandard": null
                        }
                    ]
                },
                {
                    "Id": 5,
                    "Kostnadsslag": "Indirekta kostnader",
                    "KostnaderPerAr": [
                        {
                            "Ar": 2015,
                            "Summa": 0,
                            "AndringsmarkeringarUtokad": null,
                            "AndringsmarkeringarStandard": null
                        },
                        {
                            "Ar": 2016,
                            "Summa": 0,
                            "AndringsmarkeringarUtokad": null,
                            "AndringsmarkeringarStandard": null
                        }
                    ]
                }
            ],
            "BidragPerAr": [],
            "Finansiarer": []
        },
        {
            "IregKey": "<key type='20' id='58880'/>",
            "IregId": 58880,
            "Koordinerande": false,
            "Organisationsnamn": "HEMNET SERVICE HNS AB",
            "Arbetsplatsnamn": "HEMNET SERVICE HNS AB",
            "Organisationsnummer": "556260-0089",
            "Kostnader": [
                {
                    "Id": 1,
                    "Kostnadsslag": "Personalkostnader",
                    "KostnaderPerAr": [
                        {
                            "Ar": 2015,
                            "Summa": 0,
                            "AndringsmarkeringarUtokad": null,
                            "AndringsmarkeringarStandard": null
                        },
                        {
                            "Ar": 2016,
                            "Summa": 0,
                            "AndringsmarkeringarUtokad": null,
                            "AndringsmarkeringarStandard": null
                        }
                    ]
                },
                {
                    "Id": 2,
                    "Kostnadsslag": "Utrustning, mark, byggnader",
                    "KostnaderPerAr": [
                        {
                            "Ar": 2015,
                            "Summa": 0,
                            "AndringsmarkeringarUtokad": null,
                            "AndringsmarkeringarStandard": null
                        },
                        {
                            "Ar": 2016,
                            "Summa": 0,
                            "AndringsmarkeringarUtokad": null,
                            "AndringsmarkeringarStandard": null
                        }
                    ]
                },
                {
                    "Id": 3,
                    "Kostnadsslag": "Konsultkostnader, licenser m.m",
                    "KostnaderPerAr": [
                        {
                            "Ar": 2015,
                            "Summa": 0,
                            "AndringsmarkeringarUtokad": null,
                            "AndringsmarkeringarStandard": null
                        },
                        {
                            "Ar": 2016,
                            "Summa": 0,
                            "AndringsmarkeringarUtokad": null,
                            "AndringsmarkeringarStandard": null
                        }
                    ]
                },
                {
                    "Id": 4,
                    "Kostnadsslag": "Övriga direkta kostnader inkl. resor",
                    "KostnaderPerAr": [
                        {
                            "Ar": 2015,
                            "Summa": 0,
                            "AndringsmarkeringarUtokad": null,
                            "AndringsmarkeringarStandard": null
                        },
                        {
                            "Ar": 2016,
                            "Summa": 0,
                            "AndringsmarkeringarUtokad": null,
                            "AndringsmarkeringarStandard": null
                        }
                    ]
                },
                {
                    "Id": 5,
                    "Kostnadsslag": "Indirekta kostnader",
                    "KostnaderPerAr": [
                        {
                            "Ar": 2015,
                            "Summa": 0,
                            "AndringsmarkeringarUtokad": null,
                            "AndringsmarkeringarStandard": null
                        },
                        {
                            "Ar": 2016,
                            "Summa": 0,
                            "AndringsmarkeringarUtokad": null,
                            "AndringsmarkeringarStandard": null
                        }
                    ]
                }
            ],
            "BidragPerAr": [],
            "Finansiarer": []
        }
    ],
    "Links": null,
    "OpenedFirstTime": true,
    "Ansokansniva": 2,
    "Kompletteringsniva": 4
}
khellang commented 8 years ago

That's not the whole DTO/Entity/Representation (whatever it's called), it's just the enum. I assume that Ansokansniva is of type ModelNiva?

This sounds really weird. Have you tried taking the JSON payload and deserializing it using JsonConvert to see if you get the same result? I'm pretty sure Nancy isn't doing any magic here.

LundinMichael commented 8 years ago

Yes, Ansokansniva is of type ModelNiva.

public class AnsokanBudgetUtokad
{
    public int Id { get; set; }
    public int Version { get; set; }
    public int AnsverId { get; set; }
    public ModelNiva Budgetniva { get; set; }
    public DateTime? StartDatum { get; set; }
    public DateTime? SlutDatum { get; set; }
    public bool AddProjektparter { get; set; }
    public bool AddFinansiarer { get; set; }
    public bool Nivaskillnad { get; set; }
    public IList<ProjektpartUtokad> Projektparter { get; set; }
    public BudgetUtokadLinks Links { get; set; }
    public bool OpenedFirstTime { get; set; }
    public ModelNiva Ansokansniva { get; set; }
    public ModelNiva Kompletteringsniva { get; set; }
}

Yeah, I've done that now, using JsonConvert, and then it's working fine so that's how I've done as a fix for now. It's really weird, and when I uninstall Nancy.Serialization.JsonNet it works fine again?

rasmus-beck commented 8 years ago

I have been using Nancy.Serialization.JsonNet with our API for a long time now, and not had any trouble exposing enums either. I have chosen to expose them with their text representation though. I find it much easier to read the JSON document that way. For that to work, you need to create a JsonNetBodyDeserializer and a JsonNetSerializer.

Try creating these classes:

    public class MyJsonBodyDeserializer : JsonNetBodyDeserializer
    {
        public MyJsonBodyDeserializer()
            : base(JSonSerializationConfigurator.ConfiguredSerializer())
        { }
    }

    public class MyJsonSerializer : JsonNetSerializer
    {
        public MyJsonSerializer()
            : base(JSonSerializationConfigurator.ConfiguredSerializer())
        { }
    }

    public class JSonSerializationConfigurator
    {
        public static JsonSerializer ConfiguredSerializer()
        {
            var serializer = new JsonSerializer ();
            serializer.Converters.Add( new StringEnumConverter () );
            return serializer;
        }
    }

In your bootstrapper override the default serializers

        protected override NancyInternalConfiguration InternalConfiguration
        {
            get
            {
                return NancyInternalConfiguration.WithOverrides(
                    builder =>
                    {
                        builder.Serializers = new[]
                                {
                                    typeof (MyJsonSerializer)
                                };
                    });
            }
        }

        protected override IEnumerable<Type> BodyDeserializers
        {
            get
            {
                return new List<Type> { typeof(MyJsonBodyDeserializer) };
            }
        }

Don't know if it will make a difference, but that is how I got my Enums to work for me.