0

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.

1 Answer 1

1

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);
    }
}
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.