Reputation: 4987
I have a Web API method returning a List<AttributeCollection>
. AttributeCollection
is kind of a list of, obviously, attributes with values for each attributes (in this case fetched by the CRM 2011 SDK).
Here is the JSON that the method returns:
[
[
{
"Key": "mobilephone",
"Value": "(430) 565-1212"
},
{
"Key": "firstname",
"Value": "John"
}
],
[
{
"Key": "mobilephone",
"Value": "(430) 565-1313"
},
{
"Key": "firstname",
"Value": "Mark"
}
]
]
Now, the first pair of brackets are a visual representation of the List, and then you have many pairs of brackets ([]
) for each AttributeCollection
.
I want to get rid of the first pair of brackets, replace it with a top level element name (ie: allAttributes
) and then all items following.
I am overidding the WriteToStreamAsync
method of JsonMediaTypeFormatter
public override System.Threading.Tasks.Task WriteToStreamAsync(Type type, object value, System.IO.Stream writeStream, HttpContent content, TransportContext transportContext)
{
if ((typeof(IEnumerable<AttributeCollection>).IsAssignableFrom(type)))
{
//anything I could do here ?
}
return base.WriteToStreamAsync(type, value, writeStream, content, transportContext);
}
I thought of manipulating the JSON string itself, but it doesn't seem accessible from there.
Any ideas ?
Thanks.
Upvotes: 0
Views: 138
Reputation: 87228
If you want to do that on the formatter itself, you may want to write the wrapping code to the writeStream
, as in the code below (tested in Notepad):
public override async Task WriteToStreamAsync(Type type, object value, Stream writeStream, HttpContent content, TransportContext transportContext)
{
if ((typeof(IEnumerable<AttributeCollection>).IsAssignableFrom(type)))
{
var list = (IEnumerable<AttributeCollection>)value;
byte[] headerBytes = Encoding.UTF8.GetBytes("{\"allAttributes\":");
byte[] footerBytes = Encoding.UTF8.GetBytes("}");
writeStream.Write(headerBytes, 0, headerBytes.Length);
foreach (var item in list)
{
await base.WriteToStreamAsync(item.GetType(), item, writeStream, content, transportContext);
}
writeStream.Write(footerBytes, 0, footerBytes.Length);
}
else
{
return await base.WriteToStreamAsync(type, value, writeStream, content, transportContext);
}
}
Another alternative would be to create a wrapping class and serialize it:
public class MyWrappingClass
{
public IEnumerable<AttributeCollection> allAttributes { get; set; }
}
public override Task WriteToStreamAsync(Type type, object value, Stream writeStream, HttpContent content, TransportContext transportContext)
{
if ((typeof(IEnumerable<AttributeCollection>).IsAssignableFrom(type)))
{
var list = (IEnumerable<AttributeCollection>)value;
var obj = new MyWrappingClass { allAttributes = list };
return base.WriteToStreamAsync(obj.GetType(), obj, writeStream, content, transportContext);
}
else
{
return base.WriteToStreamAsync(type, value, writeStream, content, transportContext);
}
}
Upvotes: 1