Home » Serialization
Category Archives: Serialization
Change the Data Serialization Format in the Sitecore Item Web API
I had a major urge yesterday to continue my tinkering of the Sitecore Item Web API, and wondered how one would go about changing the serialization format of its response.
Without re-reading the documentation on how one could go about doing this — I forgot that this was discussed in its documentation (check out pages 16-17 in the Sitecore Item Web API 1.0.0 Developer’s Guide where you can see how to use an XML serializer) — I tackled this by experimentation, and came up with a slightly different solution than the one offered in the Developer’s Guide.
I considered using an XML serializer for this blog post, but decided to fish around on the internet to see what other data serialization formats exist, and discovered YAML — a format that looks similar to JSON.
I continued my internet surfing — I mean research — and found a .NET library — YamlDotNet — that assists developers in converting objects into YAML, and decided to give it a go.
The following Sitecore item Web API Serializer uses this YAML library:
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using Sitecore.Diagnostics;
using Sitecore.ItemWebApi.Serialization;
using YamlDotNet.RepresentationModel.Serialization;
namespace Sitecore.Sandbox.ItemWebApi.Serialization
{
public class YamlSerializer : ISerializer
{
// Serializer in YamlDotNet.RepresentationModel.Serialization
private static readonly Serializer Serializer = new Serializer();
public YamlSerializer()
{
}
public string Serialize(object value)
{
Assert.ArgumentNotNull(value, "value");
string yaml = string.Empty;
using(StringWriter stringWriter = new StringWriter())
{
Serializer.Serialize(stringWriter, value);
yaml = stringWriter.ToString();
}
return yaml;
}
public string SerializedDataMediaType
{
get
{
return "application/x-yaml";
}
}
}
}
The Serializer above just delegates responsibility to the YamlDotNet’s YAML serializer.
Now that we have our YamlSerializer ready to go, we have to somehow wire it up to the Sitecore Item Web API.
After some digging in Sitecore.ItemWebApi.dll, I learned the out of the box JsonSerializer is set in a preprocessRequest pipeline processor:
Following this lead, I created a custom preprocessRequest pipeline processor for setting our new YamlSerializer:
using System;
using System.Web;
using Sitecore.Pipelines.PreprocessRequest;
using Sitecore.Diagnostics;
using Sitecore.ItemWebApi.Serialization;
using Sitecore.Sandbox.ItemWebApi.Serialization;
namespace Sitecore.Sandbox.ItemWebApi.Pipelines.PreprocessRequest
{
public class ResolveSerializer : PreprocessRequestProcessor
{
public override void Process(PreprocessRequestArgs arguments)
{
Assert.ArgumentNotNull(arguments, "arguments");
Assert.ArgumentNotNull(arguments.Context, "arguments.Context");
Assert.ArgumentNotNull(arguments.Context.Request, "arguments.Context.Request");
ISerializer serializer = GetSerializer(arguments.Context.Request);
if (serializer != null)
{
Sitecore.ItemWebApi.Context.Current.Serializer = serializer;
}
}
private static ISerializer GetSerializer(HttpRequest request)
{
if(IsYamlRequest(request))
{
return new YamlSerializer();
}
return null;
}
private static bool IsYamlRequest(HttpRequest request)
{
Assert.ArgumentNotNull(request, "request");
return string.Equals(request["format"], "yaml", StringComparison.CurrentCultureIgnoreCase);
}
}
}
We only set our YamlSerializer when client code requests data to be returned as YAML — this is made known when the client code sets “Yaml” in a HTTP request parameter named “format” (an example of this would be &format=Yaml via a query string).
I then added the new preprocessRequest pipeline processor in \App_Config\Include\Sitecore.ItemWebApi.config, and made sure it’s called right after /configuration/sitecore/pipelines/preprocessRequest/processor[@type=”Sitecore.ItemWebApi.Pipelines.PreprocessRequest.RewriteUrl, Sitecore.ItemWebApi”] — default instances are set here on the Sitecore Item Web API’s Context instance, and we should ensure this object exits before changing properties on it:
<?xml version="1.0" encoding="utf-8"?> <configuration xmlns:patch="http://www.sitecore.net/xmlconfig/"> <sitecore> <pipelines> <!-- there is stuff up here --> <preprocessRequest> <processor type="Sitecore.Sandbox.ItemWebApi.Pipelines.PreprocessRequest.ResolveSerializer, Sitecore.Sandbox" patch:before="processor[@type='Sitecore.Pipelines.PreprocessRequest.CheckIgnoreFlag, Sitecore.Kernel']" /> <processor type="Sitecore.ItemWebApi.Pipelines.PreprocessRequest.RewriteUrl, Sitecore.ItemWebApi" patch:before="processor[@type='Sitecore.Sandbox.ItemWebApi.Pipelines.PreprocessRequest.ResolveSerializer, Sitecore.Sandbox']" /> </preprocessRequest> <!-- and more stuff down here --> </sitecore> </configuration>
After modifying some code in my copy of the console application written by Kern Herskind Nightingale, Director of Technical Services at Sitecore UK — I added &format=yaml as a query string parameter — I invoked it to retrieve an item in my local instance of Sitecore:
As you can see, the response is now in YAML.
If you have any thoughts on this, or have any recommendations on using other serialization formats, please drop a comment.
Add Additional Item Properties in Sitecore Item Web API Responses
The other day I was exploring pipelines of the Sitecore Item Web API, and took note of the itemWebApiGetProperties pipeline. This pipeline adds information about an item in the response returned by the Sitecore Item Web API. You can find this pipeline at /configuration/sitecore/pipelines/itemWebApiGetProperties in \App_Config\Include\Sitecore.ItemWebApi.config.
The following properties are set for an item in the response via the lonely pipeline processor — /configuration/sitecore/pipelines/itemWebApiGetProperties/processor[@type=”Sitecore.ItemWebApi.Pipelines.GetProperties.GetProperties, Sitecore.ItemWebApi”] — that ships with the Sitecore Item Web API:
Here’s an example of what the properties set by the above pipeline processor look like in the response — I invoked a read request to the Sitecore Item Web API via a copy of the console application written by Kern Herskind Nightingale, Director of Technical Services at Sitecore UK:
You might be asking “how difficult would it be to add in my own properties?” It’s not difficult at all!
I whipped up the following itemWebApiGetProperties pipeline processor to show how one can add more properties for an item:
using Sitecore.Data.Items;
using Sitecore.Diagnostics;
using Sitecore.ItemWebApi;
using Sitecore.ItemWebApi.Pipelines.GetProperties;
namespace Sitecore.Sandbox.ItemWebApi.Pipelines.GetProperties
{
public class GetEvenMoreProperties : GetPropertiesProcessor
{
public override void Process(GetPropertiesArgs arguments)
{
Assert.ArgumentNotNull(arguments, "arguments");
arguments.Properties.Add("ParentID", arguments.Item.ParentID.ToString());
arguments.Properties.Add("ChildrenCount", arguments.Item.Children.Count);
arguments.Properties.Add("Level", arguments.Item.Axes.Level);
arguments.Properties.Add("IsItemClone", arguments.Item.IsItemClone);
arguments.Properties.Add("CreatedBy", arguments.Item["__Created by"]);
arguments.Properties.Add("UpdatedBy", GetItemUpdatedBy(arguments.Item));
}
private static Dynamic GetItemUpdatedBy(Item item)
{
Assert.ArgumentNotNull(item, "item");
string[] usernamePieces = item["__Updated by"].Split('\\');
Dynamic username = new Dynamic();
if (usernamePieces.Length > 1)
{
username["Domain"] = usernamePieces[0];
username["Username"] = usernamePieces[1];
}
else if (usernamePieces.Length > 0)
{
username["Username"] = usernamePieces[0];
}
return username;
}
}
}
The ParentID, ChildrenCount, Level and IsItemClone properties are simply added to the properties SortedDictionary within the GetPropertiesArgs instance, and will be serialized as is.
For the UpdatedBy property, I decided to leverage the Sitecore.ItemWebApi.Dynamic class in order to have the username set in the “__Updated by” field be represented by a JSON object. This JSON object sets the domain and username — without the domain — into different JSON properties.
As a side note — when writing your own service code for the Sitecore Item Web API — I strongly recommend using instances of the Sitecore.ItemWebApi.Dynamic class — or something similar — for complex objects. Developers writing code to consume your JSON will thank you many times for it. 🙂
I registered my new processor to the itemWebApiGetProperties pipeline in my Sitecore instance’s \App_Config\Include\Sitecore.ItemWebApi.config:
<?xml version="1.0" encoding="utf-8"?>
<configuration xmlns:patch="http://www.sitecore.net/xmlconfig/">
<sitecore>
<pipelines>
<!-- there's stuff here -->
<itemWebApiGetProperties>
<processor type="Sitecore.ItemWebApi.Pipelines.GetProperties.GetProperties, Sitecore.ItemWebApi" />
<processor type="Sitecore.Sandbox.ItemWebApi.Pipelines.GetProperties.GetEvenMoreProperties, Sitecore.Sandbox" />
</itemWebApiGetProperties>
<!-- there's stuff here as well -->
</sitecore>
</configuration>
Let’s take this for a spin.
I ran the console application again to see what the response now looks like:
As you can see, our additional properties are now included in the response.
If you can think of other item properties that would be useful for Sitecore Item Web API client applications, please share in a comment.
Until next time, have a Sitecorelicious day!












