0

I'm getting data in json format from different sources and I'm trying to map them to objects implementing the same interface.

The json variable looks something like this from feed 1:

{"identifier": 232, "type": "Feed1"}

And I'm serializing it using this object:

   [DataContract]
    public class Class A : InterfaceA
    {

        [DataMember(Name = "identifier")]
        public int Id{ get; set; }

        [DataMember(Name = "type")]
        public FeedType Type { get; set; }
    }

    [DataContract]
    public enum FeedType
    {
        [EnumMember(Value = "Feed1")]
        FeedA,
        [EnumMember(Value = "Feed2")]
        FeedB,
        [EnumMember(Value = "Feed3")]
        FeedC
    }

The interface looks like this:

public interface InterfaceA
{
   int Id {get;set;}
   FeedType Type{get;set;}
}

In feed 2, the object looks like this:

{"identifier": 232, "feedType": "A"}

How can I create another object that implements the same interface and will return the same enum? How do I set up the DataContract?

EDIT:

I serialize it like this

            var serializer = new DataContractJsonSerializer(ClassA);

            var ms = new MemoryStream(Encoding.Unicode.GetBytes(json));
            var serializedObject = serializer.ReadObject(ms);
dbc
  • 104,963
  • 20
  • 228
  • 340
johan
  • 6,578
  • 6
  • 46
  • 68
  • first things first, you cannot create an instance of an interface so you will need to create an instance of an actual class, have you thought about using a generic method? – Liam Nov 13 '12 at 16:19
  • Can you include the code where you actually seralize the Json too? – Liam Nov 13 '12 at 16:23
  • @Liam I did think about generic types. But I would like it to be the same type of enum. – johan Nov 13 '12 at 16:26

2 Answers2

1

I'll give an answer using Json.Net (of course if you are open to use a different serializer)

string json = @"{""identifier"": 232, ""type"": ""Feed2""}";
var classa = JsonConvert.DeserializeObject<ClassA>(json);

.

public interface InterfaceA
{
    int Id { get; set; }
    FeedType Type { get; set; }
}

public class ClassA : InterfaceA
{
    [JsonProperty("identifier")]
    public int Id{ get; set; }

    [JsonConverter(typeof(MyConverter))] //<--- !!!
    [JsonProperty("type")]
    public FeedType Type { get; set; }
}

[DataContract]
public enum FeedType
{
    [EnumMember(Value = "Feed1")]
    FeedA,
    [EnumMember(Value = "Feed2")]
    FeedB,
    [EnumMember(Value = "Feed3")]
    FeedC
}

And this is the type converter class

public class MyConverter : Newtonsoft.Json.Converters.StringEnumConverter
{
    public override bool CanConvert(Type objectType)
    {
        return objectType == typeof(FeedType);
    }


    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        var field = objectType.GetFields()
            .First(f => f.GetCustomAttributes(false)
                         .Any(a=>a.GetType()==typeof(EnumMemberAttribute) &&
                                 ((EnumMemberAttribute)a).Value.Equals(reader.Value))); 



        return field.GetValue(null);
    }
}
L.B
  • 114,136
  • 19
  • 178
  • 224
  • Exactly like that, but I would prefer not having to swith serializer – johan Nov 13 '12 at 17:17
  • @johan As you can see it gives much more control over serialization/deserialization process than other serializers. (BTW MVC4 also uses it). – L.B Nov 13 '12 at 17:22
  • 1
    Well, since I'm not getting any other answer I guess is the best solution. Thanks – johan Nov 14 '12 at 15:45
0

so if you want a class B

[DataContract]
    public class ClassB : InterfaceA
    {

        [DataMember(Name = "identifier")]
        public int Id{ get; set; }

        [DataMember(Name = "type")]
        public FeedType Type { get; set; }
    }

var serializer = new DataContractJsonSerializer(ClassB);

            var ms = new MemoryStream(Encoding.Unicode.GetBytes(json));
            var serializedObject = serializer.ReadObject(ms);

Thats it?! you could use a generic if you wanted to reuse the code:

public T SerialiseObject<T>(string json) where T : InterfaceA
{
var serializer = new DataContractJsonSerializer(T);

var ms = new MemoryStream(Encoding.Unicode.GetBytes(json));
 return (T)serializer.ReadObject(ms);
}

then call it:

SerialiseObject<ClassA>(json);
SerialiseObject<ClassB>(json);

to explain more fully you could not have

public class ClassA : InterfaceA
{
 public ns1.FeedType Type{get; set;}
}

and

public class ClassB : InterfaceA
{
  public ns2.FeedType Type{get; set;}
}

this would not compile as InterfaceA would expect either ns1.FeedType or ns2.FeedType

Liam
  • 27,717
  • 28
  • 128
  • 190
  • Thanks, but I don't think that answers my question. How would that serialize "feedType" in the second json response correctly to the enum? – johan Nov 13 '12 at 16:38
  • FeedType would be the same type in both? It'd need to be or else it would break the interface declaration? – Liam Nov 13 '12 at 17:04
  • I understand that fully. But you solution wouldn't work as the json looks different. What you explain as not a funtional solution would work if the interface uses generic types. – johan Nov 13 '12 at 17:11