Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/22.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# JSON.NET中特定对象的自定义转换_C#_.net_Json_Json.net - Fatal编程技术网

C# JSON.NET中特定对象的自定义转换

C# JSON.NET中特定对象的自定义转换,c#,.net,json,json.net,C#,.net,Json,Json.net,我正在使用JSON.NET序列化我的一些对象,我想知道是否有一种简单的方法可以仅为特定对象覆盖默认的JSON.NET转换器 目前我有以下课程: public class ChannelContext : IDataContext { public int Id { get; set; } public string Name { get; set; } public IEnumerable<INewsItem> Items { get; set; } } 该

我正在使用JSON.NET序列化我的一些对象,我想知道是否有一种简单的方法可以仅为特定对象覆盖默认的JSON.NET转换器

目前我有以下课程:

public class ChannelContext : IDataContext
{
    public int Id { get; set; }
    public string Name { get; set; }
    public IEnumerable<INewsItem> Items { get; set; }
}
该特定类是否可以改为采用这种格式:

"Id_2":
{
    "Name": "name value",
    "Items": [ item data here ]
}
我对JSON.NET有点陌生。。我想知道上述内容是否与编写自定义转换器有关。我找不到任何关于如何写一个的具体例子,如果有人能给我指出一个具体的来源,我将非常感激

我需要找到一个解决方案,使特定的类总是转换为相同的,因为上面的上下文是一个更大的上下文的一部分,JSON.NET默认转换器可以很好地转换它

希望我的问题足够清楚

更新:

我发现了如何创建新的自定义转换器(通过创建从JsonConverter继承的新类并重写其抽象方法),我重写了WriteJson方法,如下所示:

public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        ChannelContext contextObj = value as ChannelContext;

        writer.WriteStartObject();
        writer.WritePropertyName("id_" + contextObj.Id);
        writer.WriteStartObject();
        writer.WritePropertyName("Name");
        serializer.Serialize(writer, contextObj.Name);

        writer.WritePropertyName("Items");
        serializer.Serialize(writer, contextObj.Items);
        writer.WriteEndObject();
        writer.WriteEndObject();
    }
这确实很成功,但是。。。 我很好奇是否有一种方法可以通过重用默认的JsonSerializer(或转换器)而不是使用jsonwriter方法手动“编写”对象来序列化其余的对象属性

更新2: 我试图得到一个更通用的解决方案,并提出了以下建议:

public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        writer.WriteStartObject();

        // Write associative array field name
        writer.WritePropertyName(m_FieldNameResolver.ResolveFieldName(value));

        // Remove this converter from serializer converters collection
        serializer.Converters.Remove(this);

        // Serialize the object data using the rest of the converters
        serializer.Serialize(writer, value);

        writer.WriteEndObject();
    }
public class ResponseContext
{
    private List<ChannelContext> m_Channels;

    public ResponseContext()
    {
        m_Channels = new List<ChannelContext>();
    }

    public HeaderContext Header { get; set; }

    [JsonConverter(
        typeof(AssociativeArraysConverter<ChannelContextFieldNameResolver>))]
    public List<ChannelContext> Channels
    {
        get { return m_Channels; }
    }

}

[JsonObject(MemberSerialization = MemberSerialization.OptOut)]
public class ChannelContext : IDataContext
{
    [JsonIgnore]
    public int Id { get; set; }

    [JsonIgnore]
    public string NominalId { get; set; }

    public string Name { get; set; }

    public IEnumerable<Item> Items { get; set; }
}
在将转换器手动添加到序列化程序时,这可以正常工作,如下所示:

jsonSerializer.Converters.Add(new AssociativeArraysConverter<DefaultFieldNameResolver>());
jsonSerializer.Serialize(writer, channelContextObj);
这显然是因为我的自定义转换器现在被认为是类的默认转换器,一旦它被设置为JsonConverterAttribute,那么我就会得到一个INIFIENT循环。 为了解决这个问题,我唯一能想到的是从一个基本的jsonconverter类继承,并调用base.serialize()方法来代替。。。 但这样的JsonConverter类是否存在

非常感谢


Mikey

如果有人对我的解决方案感兴趣:

在序列化某些集合时,我想创建一个关联的json数组,而不是标准的json数组,这样我的同事客户端开发人员就可以高效地访问这些字段,使用它们的名称(或键),而不是遍历它们

考虑以下几点:

public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        writer.WriteStartObject();

        // Write associative array field name
        writer.WritePropertyName(m_FieldNameResolver.ResolveFieldName(value));

        // Remove this converter from serializer converters collection
        serializer.Converters.Remove(this);

        // Serialize the object data using the rest of the converters
        serializer.Serialize(writer, value);

        writer.WriteEndObject();
    }
public class ResponseContext
{
    private List<ChannelContext> m_Channels;

    public ResponseContext()
    {
        m_Channels = new List<ChannelContext>();
    }

    public HeaderContext Header { get; set; }

    [JsonConverter(
        typeof(AssociativeArraysConverter<ChannelContextFieldNameResolver>))]
    public List<ChannelContext> Channels
    {
        get { return m_Channels; }
    }

}

[JsonObject(MemberSerialization = MemberSerialization.OptOut)]
public class ChannelContext : IDataContext
{
    [JsonIgnore]
    public int Id { get; set; }

    [JsonIgnore]
    public string NominalId { get; set; }

    public string Name { get; set; }

    public IEnumerable<Item> Items { get; set; }
}
由于我想在其他上下文中也使用上述内容,并且我可能决定使用不同的属性作为其“键”,或者甚至可能选择创建自己的唯一名称,这与任何属性都无关,因此我需要某种通用解决方案,因此我编写了一个名为AssociateArraySConverter的通用类,它以以下方式从JsonConverter继承:

public class AssociativeArraysConverter<T> : JsonConverter
    where T : IAssociateFieldNameResolver, new()
{
    private T m_FieldNameResolver;

    public AssociativeArraysConverter()
    {
        m_FieldNameResolver = new T();
    }

    public override bool CanConvert(Type objectType)
    {
        return typeof(IEnumerable).IsAssignableFrom(objectType) &&
                !typeof(string).IsAssignableFrom(objectType);
    }

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        IEnumerable collectionObj = value as IEnumerable;

        writer.WriteStartObject();

        foreach (object currObj in collectionObj)
        {
            writer.WritePropertyName(m_FieldNameResolver.ResolveFieldName(currObj));
            serializer.Serialize(writer, currObj);
        }

        writer.WriteEndObject();
    }
}
现在剩下要做的就是创建一个类,该类实现IASociateFieldNameResolver的单个函数,该函数接受集合中的每个项,并基于该对象返回一个字符串,该字符串将作为项的关联对象的键

此类类的示例如下:

public class ChannelContextFieldNameResolver : IAssociateFieldNameResolver
{
    public string ResolveFieldName(object i_Object)
    {
        return (i_Object as ChannelContext).NominalId;
    }
}

在重写JsonConverter时,如何避免为ReadJson提供实现?
public interface IAssociateFieldNameResolver
{
    string ResolveFieldName(object i_Object);
}
public class ChannelContextFieldNameResolver : IAssociateFieldNameResolver
{
    public string ResolveFieldName(object i_Object)
    {
        return (i_Object as ChannelContext).NominalId;
    }
}