1

I'm atempting to use the same class structure for a web api function which should return either json or xml - whichever the client requires.

However, the structure requirements are a little different from json to xml.

The XML should look like this:

    <prtg>
       <result>
        <channel>First channel</channel>
        <value>10</value>
       </result>
       <result>
        <channel>Second channel</channel>
        <value>20</value>
       </result>
    </prtg>

And the JSON should look like this

     {
      "prtg": {
       "result": [
        {
         "channel": "First channel",
         "value": "10"
        },
        {
         "channel": "Second channel",
         "value": "20"
        }
       ]
      }
     }

I'm unable to make this interchangable.

The classes I'm serializing are thus:

[DataContract]
public class PrtgModel
{
    [DataMember]
    public Prtg Prtg { get; set; } = new Prtg();
}

//[JsonObject(NamingStrategyType = typeof(Newtonsoft.Json.Serialization.CamelCaseNamingStrategy))]
[DataContract]
public class Prtg
{
    [DataMember]
    public IList<PrtgResult> Result { get; set; } = new List<PrtgResult>();
}

//[JsonObject(NamingStrategyType = typeof(Newtonsoft.Json.Serialization.CamelCaseNamingStrategy))]
[DataContract]
public class PrtgResult
{
    [DataMember]
    public string Channel { get; set; }
    [DataMember]
    public string Value { get; set; }
    //[JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
    [DataMember]
    public int? LimitMaxError { get; set; }
    //[JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
    [DataMember]
    public int? LimitMinError { get; set; }
    //[JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
    [DataMember]
    public string LimitErrorMsg { get; set; }
    //[JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
    [DataMember]
    public int? LimitMode { get; set; } // 0=no, 1=yes
}

This renders the correct JSON, but if i request XML I get the PrtgResult element also. Looking at https://learn.microsoft.com/en-us/dotnet/standard/serialization/controlling-xml-serialization-using-attributes#controlling-serialization-of-classes-using-xmlrootattribute-and-xmltypeattribute doesn't quite show how to flatten the array the way i require.

Is this really possible with annotation without completely overriding the xml generation?

Vincent
  • 1,119
  • 11
  • 25
  • could you please show your serialization code for both json and xml? – er-sho Nov 27 '18 at 11:34
  • I don't do serialization manually. This is a web api. – Vincent Nov 27 '18 at 11:35
  • Could you add a `Result` property directly to your `PrtgModel` class? You'd have to populate both `Result` and `Prtg.Result`, and would use attributes to serialize properly (remove `DataMember` attribute from `PrtgModel.Prtg`, add `DataMember` to `PrtgModel.Result`, add `JsonIgnore` to `PrtgModel.Result`) – Joe Nov 27 '18 at 11:43
  • Clever, I'll try. – Vincent Nov 27 '18 at 11:46
  • It was a good suggestion @Joe, but unfortunately decorating a class with DataContract makes the properties opt-in, so unless i have DataMember on the PrtgModel.Prtg it won't be serialized when requesting json. Also IgnoreDataMember is respected by both DataContractSerializer and JsonSerializer. – Vincent Nov 27 '18 at 12:19
  • @Vincent, something learnt today; I didn't realize Json.net respected DataContract / DataMember attributes. One possible workaround is the following, https://stackoverflow.com/a/39300347/13087 – Joe Nov 27 '18 at 14:35
  • You want to serialize the `IList Result { get; set; }` list without an outer element, but this is not supported by `DataContractSerializer`, see [Data Contract Serializer - How to omit the outer element of a collection](https://stackoverflow.com/q/8591045), instead you will have to switch to `XmlSerializer`. Since you are using web api see [XmlSerializer ignores `[XmlAttribute]` in WebApi](https://stackoverflow.com/a/35846977) and then [Deserializing into a List without a container element in XML](https://stackoverflow.com/q/5271442). – dbc Nov 27 '18 at 15:36

0 Answers0