【问题标题】:How to bind a given property when deserializing a JSON object in c# Web Api?在 c# Web Api 中反序列化 JSON 对象时如何绑定给定属性?
【发布时间】:2015-07-23 15:23:53
【问题描述】:

我有一个看起来像的 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 表示数据库标识符。因此,为了正确绑定到我的模型,我需要编写一个自定义 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 项目不是对象:整数。路径 ParentNode'”,如何调整 ReadJson 方法以绑定 ParentNode 属性或其他需要自定义转换的东西?

更新

我看到了JsonPropertyAttribute 的 API 文档说明

指示 JsonSerializer 始终序列化具有指定名称的成员

但是,我如何以编程方式指示 JsonSerializer(在我的例子中,在 ReadJson 方法中)使用给定的 JsonPropertyAttribute ?

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

【问题讨论】:

  • 1) 你需要序列化,还是只反序列化? 2) 假设你已经读取了父节点ID,如何让父节点设置在子节点中?

标签: c# asp.net json asp.net-web-api


【解决方案1】:

您可以使用私有设置器创建公共 ParentNodeId 和 ParentNode。然后传递 ParentNodeId,该 setter 将在其中执行代码以填充 ParentNode。现在您可以将您的模型序列化为 JSON 并将其传递回客户端……或者您想用它做什么。类似的,

public class Node {

public int Id { get; set; }

/** Properties omitted for sake of brevity **/
private int _parentNodeId;
public int ParentNodeId { get {return _parentNodeId;}
set
{
    _parentNodeId = value;
    ParentNode = GetParentNodePropertyValues(_parentNodeId);
} 
}
public Node ParentNode { get; private set; }

}

【讨论】:

    【解决方案2】:

    我认为这里的问题是由于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;
    }
    

    【讨论】:

    • 非常感谢!你拯救了我的一天。
    猜你喜欢
    • 2013-07-29
    • 2021-06-16
    • 1970-01-01
    • 2013-09-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多