0

我想使用 json.net 来序列化 jquery ui 小部件的选项,例如 jquery 手风琴。

但是手风琴有一个属性active可以是以下之一:

一个基于 0 的整数,它定义了一个活动选项卡,

一个布尔值,当设置为 false 时,将折叠所有手风琴。

我正在考虑创建 2 个可为空的 .NET 属性:

int? Active

bool? IsActive

如果 Active 不为空,则应将其序列化为具有属性名称的整数active,如果 IsActive 不为空,则应将其序列化为具有相同名称的布尔值active。.Net 代码将确保其中只有一个不能为空。

但是当我将 [JsonProperty("active")] 放在两个属性上时,它不起作用......还有其他选择吗?

4

1 回答 1

0

您当前方法的困难在于,拥有这两个字段将不起作用,因为您无法同时标记它们[JsonProperty("active")]。我的第一次尝试是定义类如下:

class Accordion
{
    [JsonProperty("active")]
    [JsonConverter(typeof(ActiveTabConverter))]
    public int Active { get; set; }

    [JsonProperty("active")]
    [JsonConverter(typeof(ActiveTabConverter))]
    public bool IsActive { get; set; }
}

这会导致异常(我想你也有这个),因为我使用[JsonProperty("active")]了两个属性。删除其中一个属性也不起作用:没有例外,但是从其中删除属性的字段从未反序列化。

起作用的是以下内容:

class Accordion
{
    [JsonProperty("active")]
    [JsonConverter(typeof(ActiveTabConverter))]
    public int Active { get; set; }

    [JsonIgnore]
    public bool IsActive
    {
        get
        {
            return this.Active > -1;
        }
    }

    public Accordion()
    {
        this.Active = -1;
    }
}

请注意,仍然有两个字段,但只有其中一个会被反序列化。是IsActive一个辅助属性。我在这里遵循的约定是Active大于 0 的值表示打开的手风琴选项卡,而 -1 相当于false从 JSON 接收。

class ActiveTabConverter : JsonConverter
{
    public override bool CanConvert(Type objectType)
    {
        return objectType == typeof(int) || objectType == typeof(bool);
    }

    public override object ReadJson(JsonReader reader, Type objectType,
        JsonSerializer serializer)
    {
        var value = JValue.ReadFrom(reader);

        if (value.Type == JTokenType.Integer)
        {
            return serializer.Deserialize<int>(reader);
        }

        return -1;
    }

    public override void WriteJson(JsonWriter writer, object value,
        JsonSerializer serializer)
    {
        int item = (int)value;

        if (item == -1)
        {
            writer.WriteValue(false);
        }
        else
        {
            writer.WriteValue(item);
        }

        writer.Flush();
    }
}

这个类负责反序列化和序列化Active值。

我使用以下代码来序列化/反序列化。请注意,JSON 实际上来自 jQuery 手风琴。对于有问题的一个属性来说,这太过分了,但我认为最好使用真实数据。

string json1 = "{\"disabled\":false,\"create\":null,\"active\":2,\"animate\":300,\"collapsible\":false,\"event\":\"click\",\"header\":\"> li > :first-child,> :not(li):even\",\"heightStyle\":\"auto\",\"icons\":{\"activeHeader\":\"ui-icon-triangle-1-s\",\"header\":\"ui-icon-triangle-1-e\",\"headerSelected\":\"ui-icon-triangle-1-s\"},\"activate\":null,\"beforeActivate\":null,\"navigation\":false,\"autoHeight\":true,\"clearStyle\":false,\"fillSpace\":false,\"change\":null,\"changestart\":null,\"animated\":\"slide\"}";
string json2 = "{\"disabled\":false,\"create\":null,\"active\":false,\"animate\":300,\"collapsible\":true,\"event\":\"click\",\"header\":\"> li > :first-child,> :not(li):even\",\"heightStyle\":\"auto\",\"icons\":{\"activeHeader\":\"ui-icon-triangle-1-s\",\"header\":\"ui-icon-triangle-1-e\",\"headerSelected\":\"ui-icon-triangle-1-s\"},\"activate\":null,\"beforeActivate\":null,\"navigation\":false,\"autoHeight\":true,\"clearStyle\":false,\"fillSpace\":false,\"change\":null,\"changestart\":null,\"animated\":\"slide\"}";

Accordion accordion = JsonConvert.DeserializeObject<Accordion>(json1);
string serializedJson = JsonConvert.SerializeObject(accordion);

accordion = JsonConvert.DeserializeObject<Accordion>(json2);
serializedJson = JsonConvert.SerializeObject(accordion);
于 2012-10-20T03:50:32.513 回答