Serializing a Sitecore.Data.Items.Item to JSON
I'm currently attempting to build a service to retrieve and serialize a Sitecore data item to JSON, so our Javascript code can access Sitecore content data.
I've tried serializing the object directly with JavascriptSerializer and JSON.Net; both broke due to recursion likely due to the various circular references on the child properties.
I've also attempted to serialize the item to XML (via item.GetOuterXml()), then converting the Xml to JSON. The conversion worked fine; but it only retrieves fields that were set on the item itself, not the fields that were set in the _standardvalues. I tried calling item.Fields.ReadAll() before serializing, as well as a foreach loop with calls to item.Fields.EnsureField(Field.id); however, neither resulted in retrieving the missing fields. However, debugging the code; the Fields array appears to contain all inherited fields from its base template as well as the ones set on the item; so I'm guessing GetOuterXml is just ignoring all fields that weren't set specifically on the item.
The more I look at this, the more it looks like I'm going to need a custom model class to encapsulate the data item and the necessary fields, decorate it with the appropriate JSON.Net serialization attributes, and serialize from there. Thi开发者_StackOverflow中文版s feels like a dirty hack though.
So before I go down this road; I wanted to know if anyone here had experience serializing Sitecore content items to JSON for client-side consumption, and is there an easier way that I'm missing. Any constructive input is greatly appreciated.
Cheers, Frank
I would suggest pursuing your approach of creating a custom model class to encapsulate just the item data you need to pass to the client. Then serialize that class to JSON. This cuts down on the amount of data you're sending over the wire and allows you to be selective about which data are being sent (for security reasons).
The CustomItem pattern and partial classes lend themselves to this approach very well. In the code samples below, the .base class is your base custom item wrapper. You can use this class to access fields and field values in a strongly-typed manner. The .instance class could be used for JSON serialization.
By splitting out the properties you want serialized, you have granular control over the data being sent back to the requesting client and you don't have to worry as much about circular references. If you need to make any changes to field definitions, you could simply change your .base class with minimal impact on your JSON serialization.
Hope this helps!
MyCustomItem.base.cs
public partial class MyCustomItem : Sitecore.Data.Items.CustomItem
{
public const string TitleFieldName = "Title";
public MyCustomItem(Item innerItem) : base(innerItem)
{
}
public static implicit operator MyCustomItem(Item innerItem)
{
return innerItem != null ? new MyCustomItem(innerItem) : null;
}
public static implicit operator Item(MyCustomItem customItem)
{
return customItem != null ? customItem.InnerItem : null;
}
public string Title
{
get { return InnerItem[TitleFieldName]); }
}
}
MyCustomItem.instance.cs
[JsonObject(MemberSerialization.OptIn)]
public partial class MyCustomItem
{
[JsonProperty("Title")]
public string JsonTitle
{
get { return Title; }
}
}
I wonder if you wouldn't be better off using an XSLT to recursively build the JSON?
精彩评论