我有一个C#类,看起来像

public class Node {

    public int Id { get; set; }

    /** Properties omitted for sake of brevity **/

    public Node ParentNode { get; set; }

}

在浏览器中,我提交了一个JSON对象,如下所示
{"Id":1, "ParentNode":1}

分配给ParentNode属性的值1表示数据库标识符。因此,为了正确绑定(bind)到我的模型,我需要编写一个自定义JSON转换器
public class NodeJsonConverter : JsonConverter
{

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        if (reader.TokenType == JsonToken.Null)
        {
            return null;
        }

        /** Load JSON from stream **/
        JObject jObject = JObject.Load(reader);

        Node node = new Node();

        /** Populate object properties **/
        serializer.Populate(jObject.CreateReader(), node);

        return node;
    }
}

因为我收到“当前JsonReader项不是对象:Integer。Path ParentNode'”的信息,所以如何适应ReadJson方法以绑定(bind)ParentNode属性或需要自定义转换的任何其他项?

更新

我见过JsonPropertyAttribute,其API文档说明



但是,如何以编程方式指示 JsonSerializer (在我的情况下为ReadJson方法)使用给定的JsonPropertyAttribute?

http://www.newtonsoft.com/json/help/html/T_Newtonsoft_Json_JsonPropertyAttribute.htm

最佳答案

我认为这里的问题是由于包含Node属性形式的NodeParentNode导致解析变得递归。

在调用serializer.Populate(jObject.CreateReader(), node);时,序列化程序将命中ParentNode类型的Node属性,然后它将尝试使用NodeJsonConverter解析该属性。那时,读者已经前进了,您不再有StartObject,而是提示您有了Integer。我认为您可以检查reader.TokenType属性以查看您是在第一个调用中还是在后续调用中,并相应地进行处理:

public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
    if (reader.TokenType == JsonToken.Null)
    {
        return null;
    }

    Node node = new Node();

    if (reader.TokenType == JsonToken.StartObject)
    {
        //initial call
        //here we have the object so we can use Populate
        JObject jObject = JObject.Load(reader);
        serializer.Populate(jObject.CreateReader(), node);
    }
    else
    {
        //the subsequent call
        //here we just have the int which is the ParentNode from the request
        //we can assign that to the Id here as this node will be set as the
        //ParentNode on the original node from the first call
        node.Id = (int)(long)reader.Value;
    }

    return node;
}

10-08 08:11
查看更多