【问题标题】:How to parse json to enum from different sources如何将json解析为来自不同来源的枚举
【发布时间】:2012-11-13 16:15:52
【问题描述】:

我从不同来源获取 json 格式的数据,并尝试将它们映射到实现相同接口的对象。

json 变量在 feed 1 中看起来像这样:

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

我正在使用这个对象对其进行序列化:

   [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
    }

界面如下:

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

在提要 2 中,对象如下所示:

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

如何创建另一个实现相同接口并返回相同枚举的对象?如何设置 DataContract?

编辑:

我是这样序列化的

            var serializer = new DataContractJsonSerializer(ClassA);

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

【问题讨论】:

  • 首先,您不能创建接口的实例,因此您需要创建实际类的实例,您是否考虑过使用泛型方法?
  • 你能把你实际序列化 Json 的代码也包括进来吗?
  • @Liam 我确实考虑过泛型类型。但我希望它是相同类型的枚举。

标签: c# .net datacontractjsonserializer


【解决方案1】:

我将使用Json.Net 给出答案(当然,如果您愿意使用不同的序列化程序)

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
}

这是类型转换器类

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);
    }
}

【讨论】:

  • 完全一样,但我宁愿不必切换序列化程序
  • @johan 正如你所看到的,它比其他序列化程序提供了对序列化/反序列化过程的更多控制。 (顺便说一句,MVC4 也使用它)。
  • 好吧,因为我没有得到任何其他答案,我想这是最好的解决方案。谢谢
【解决方案2】:

所以如果你想要一个 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);

就这样?!如果您想重用代码,可以使用泛型:

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);
}

然后调用它:

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

更全面地解释你不可能有

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

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

这不会编译为 InterfaceA 期望 ns1.FeedTypens2.FeedType

【讨论】:

  • 谢谢,但我认为这不能回答我的问题。这将如何将第二个 json 响应中的“feedType”正确序列化为枚举?
  • FeedType 在两者中会是相同的类型吗?它必须是,否则会破坏接口声明?
  • 我完全理解。但是你的解决方案不起作用,因为 json 看起来不同。如果接口使用泛型类型,您解释为不是功能性解决方案的内容将起作用。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-05
  • 2021-07-15
  • 2022-07-24
  • 1970-01-01
  • 2011-06-05
相关资源
最近更新 更多