gpt4 book ai didi

ios - 如何使用 $ref 和 $id 在 RestKit 中使用循环引用

转载 作者:可可西里 更新时间:2023-11-01 03:54:30 24 4
gpt4 key购买 nike

我有一个使用 json.net 序列化库的 API。它使用 $ref 和 $id 字段进行循环引用。 RestKit 没有意识到这些 $ref 字段正在引用另一个已经序列化的对象。

有没有办法告诉 RestKit 使用这些字段以便不创建空对象?

这是我的 json 示例:

{
"$id":"1",
"WorkOrder":{
"$id":"2",
"Location":{
"$id":"3",
"Address":{
"$id":"4",
"Guid":"8086990f-13a0-4f93-8a9b-043ff247ae66"
},
"WorkOrders":[
{
"$ref":"2"
}
],
"Guid":"ae58698d-4fcf-4c31-82bf-529077b6d059"
},
"Appointments":[
{
"$ref":"1"
}
],
"Guid":"94140fc6-9885-4395-a79d-2b60452f2bf4",
},
"Calendar":{
"$id":"5",
"OwnerID":"1bbda60d-0bda-4b97-b6e5-24460106bc54",
"IsActive":true,
"Appointments":[
{
"$ref":"1"
}
],
"Guid":"e6c91678-290d-4d12-b52f-9f6ad36dd679",
},
"Guid":"731f20c6-6ecb-4515-ade3-df47bc929c86",
}

最佳答案

答案不在 RestKit 中,而在您的 JSON.Net 序列化中。以下是问题:

  • RestKit 不知道如何处理 $ref、$id
  • 您有一个 WCF 服务层,它将您的对象返回到 API 层 (MVC APIController)。
  • 您的 API 层希望将对象序列化为 Json 到客户端。
  • WCF 需要将对象作为引用进行管理,否则会发生堆栈溢出,而您的服务只会将对象移交给 API。
  • Api 层不需要 $ref $id 引用,因为 RestKit 无法处理。
  • RestKit 可以将空对象作为仅包含对象主键的引用来处理。 RestKit 将对该对象执行 Upsert,只有主键,它会看到该对象已经存在,并且没有其他数据要更新,因此它将完美地处理引用。

因此,为了实现这一点,我们需要使用 WCF 引用将对象从我们的服务层获取到我们的 API 层,然后创建我们自己的 json 序列化,仅使用对象的主键作为引用而不是 $ WCF 使用的 id $ref 废话。

所以,这里是详细信息。

首先,您将获得 $ref $id,因为您正在调用 WCF 服务,该服务的类装饰有 [DataContract(IsReference=true)] 属性。如果您还没有用 [JsonObject(IsReference=false)] 装饰您的类,JSON.Net 序列化程序将读取此属性并创建 $id、$ref 引用。您需要 DataContract IsReference 来让您的 WCF 服务将您的对象序列化到您的 ApiController。你的 ApiController 现在想要将对象序列化为 Json 到客户端......因此你的对象也需要 Json(IsReference=false) 来防止 $id, $ref

下面是数据模型类定义现在的样子

[JsonObject(IsReference=false)]
[DataContract(IsReference=true)]
public class SomeClassToSerialize

DataContract 来自 System.Runtime.Serialization 库JsonObject 来自 NewtonSoft.Json 库

好的...这已经解决了一半。此时,我们将使用 WCF 引用将服务中的对象返回给我们的 api。我们已经告诉我们的 API 不要使用引用,所以我们的 API 服务现在会因堆栈溢出而崩溃,因为它会尝试序列化循环引用。

下一步是创建一个自定义 JsonConverter,它将仅使用主键呈现循环引用。在下面的示例中,我所有的对象都继承自 EntityBase。而这一切的主键就是一个叫做Guid的Guid。所以,这是逻辑......

跟踪 HashSet 中的所有渲染对象。如果尚未渲染对象,则循环遍历每个属性并渲染对象。如果已呈现对象,则仅呈现主键 (Guid)。

public class GuidRefJsonConverter : JsonConverter
{
public override bool CanRead { get { return false; } }
public override bool CanWrite { get { return true; } }

public override bool CanConvert(Type objectType)
{
return typeof(EntityBase).IsAssignableFrom(objectType);
}

private HashSet<EntityBase> serializedObjects = new HashSet<EntityBase>();

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

JObject jo = new JObject();
jo.Add("Guid", eb.Guid.ToString());

if (serializedObjects.Add(eb))
{
foreach (PropertyInfo prop in value.GetType().GetProperties())
{
if (prop.GetCustomAttribute<JsonIgnoreAttribute>() != null) continue;

if (prop.CanRead)
{
object propVal = prop.GetValue(value);
if (propVal != null && prop.Name!="Guid")
{
jo.Add(prop.Name, JToken.FromObject(propVal, serializer));
}
}
}

}

jo.WriteTo(writer);
}

public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
throw new NotImplementedException();
}
}

最后,我们只需要注册我们的 JsonConverter。在 WebApiConfig.Register() 方法中,只需注册序列化程序。

var json = config.Formatters.JsonFormatter;
json.SerializerSettings.Converters=new List<JsonConverter>(){new GuidRefJsonConverter()};

就是这样。 API 现在将仅使用主键序列化一个循环引用,RestKit 会将其作为一个空更新插入,并将正确映射其所有指针。

关于ios - 如何使用 $ref 和 $id 在 RestKit 中使用循环引用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21126910/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com