But i have done this in the past and it often crashes as the IPublishedContent object is so large, i would advise mapping the IPublishedContent item to a custom model manually or using models builder, and then serialise that model instead.
Best to use the UmbracoApiController class to manage a transformation of IPublishedContent as the object is too complex for JSON deserialization. You can map it to a less complex object and expose it through the controller. The controller already has access to the Umbraco Helper class which will allow you to do things link query IPC.
As the others say, out-the-box, serializing IPublishedContent object will throw various errors. The only way to do it is with a custom resolver for JSON.NET.
Then you should be able to do something like this...
@{
var settings = new JsonSerializerSettings
{
ContractResolver = new PublishedContentContractResolver()
};
var serialized = JsonConvert.SerializeObject(l, Formatting.Indented, settings);
}
I'm just trying to implement this technique but from what I can see I'm serializing twice.
public class MyController : UmbracoApiController
{
//GET:
public String GetAllThings()
{
var thingsList = Umbraco.ContentSingleAtXPath("//thingsRoot").Children;
var settings = new JsonSerializerSettings
{
ContractResolver = new PublishedContentContractResolver()
};
var serialized = JsonConvert.SerializeObject(thingsList, Formatting.Indented, settings);
return serialized;
}
}
This is giving me an output in Postman with all the escape characters showing in one big long string:
The issue you're having is the return type of the controller method, in your example it's a String. So the JSON object is being serialised into a string and that's what is being returned, (an encoded string).
Try Umbraco's JsonNetResult as the return type, it'll output as JSON (as opposed to a string).
Something like this...
public class MyController : UmbracoApiController
{
public JsonNetResult GetAllThings()
{
var thingsList = Umbraco.ContentSingleAtXPath("//thingsRoot").Children;
return new JsonNetResult
{
Data = thingsList,
Formatting = Formatting.Indented,
SerializerSettings = new JsonSerializerSettings
{
ContractResolver = new PublishedContentContractResolver()
}
};
}
}
"Message": "An error has occurred.", "ExceptionMessage": "The 'ObjectContent`1' type failed to serialize the response body for content type 'application/json; charset=utf-8'.", "ExceptionType": "System.InvalidOperationException", "StackTrace": null, "InnerException": {
"Message": "An error has occurred.",
"ExceptionMessage": "Self referencing loop detected for property 'ContentType' with type 'Umbraco.Core.Models.PublishedContent.PublishedContentType'. Path 'Data[0].ContentType.PropertyTypes[0]'.",
"ExceptionType": "Newtonsoft.Json.JsonSerializationException",
As I understand it UmbracoApiController attempts it's own JSON serialisation on return. So it appears it was doing it twice on my string and now it appears to be doing it twice at the same time. Or I may have misunderstood of course.
Funny thing is, it didn't baulk when I returned a string. So that gives me the impression the PublishedContentContractResolver is probably working. However, the UmbracoApiController's default serialisation attempt is probably the one that's blowing, which is why I was hoping to deserialise the PublishedContentContractResolver result back to a string before the UmbracoApiController did it's thing.
As I understand it, this only needs doing to stop certain IPC properties from being serialised.
I agree, it's a PITA. It would be a very elegant solution if you could just call your content and have it sent out as Json. Sounds simple, but..... ;)
I thought I'd tried that earlier but obviously not well enough, lol
That outputs perfectly now.
Thanks very much :)
So for anyone else in this predicament, the final code was:-
public class MyController : UmbracoApiController
{
//GET:
public Object GetAllThings()
{
var thingsList = Umbraco.ContentSingleAtXPath("//thingsRoot").Children;
var settings = new JsonSerializerSettings
{
ContractResolver = new PublishedContentContractResolver()
};
var serialized = JsonConvert.SerializeObject(thingsList, Formatting.Indented, settings);
return JsonConvert.DeserializeObject(serialized);
}
}
Serializing Umbraco.Content(id) to JSON
Hello , I'm New to Umbraco and I want to create Web Api. So I need help how to serialize IPublishedContent in JSON.
With Newtonsoft.Json you can:
JsonConvert.SerializeObject(Umbraco.Content(id))
But i have done this in the past and it often crashes as the IPublishedContent object is so large, i would advise mapping the IPublishedContent item to a custom model manually or using models builder, and then serialise that model instead.
Hi Sandra,
Best to use the UmbracoApiController class to manage a transformation of IPublishedContent as the object is too complex for JSON deserialization. You can map it to a less complex object and expose it through the controller. The controller already has access to the Umbraco Helper class which will allow you to do things link query IPC.
Look at the documentation here:
https://our.umbraco.com/documentation/Reference/Routing/WebApi/
Good luck,
Steve
Hi Sandra26,
As the others say, out-the-box, serializing IPublishedContent object will throw various errors. The only way to do it is with a custom resolver for JSON.NET.
See this thread for the code...
https://our.umbraco.com/forum/umbraco-8/98381-serializing-an-publishedcontentmodel-modelsbuilder-model-in-v8#comment-310148
Then you should be able to do something like this...
Hope this helps.
Cheers,
- Lee
Thank you very much for your answers, they were really helpful. You all have a nice day , Sandra
Hi,
I'm just trying to implement this technique but from what I can see I'm serializing twice.
This is giving me an output in Postman with all the escape characters showing in one big long string:
Any advice would be appreciated.
Craig
Hi Craig,
The issue you're having is the return type of the controller method, in your example it's a
String
. So the JSON object is being serialised into astring
and that's what is being returned, (an encoded string).Try Umbraco's
JsonNetResult
as the return type, it'll output as JSON (as opposed to astring
).Something like this...
Hope this helps?
Cheers,
- Lee
Thanks Lee,
I'm afraid that resulted in :-
As I understand it UmbracoApiController attempts it's own JSON serialisation on return. So it appears it was doing it twice on my string and now it appears to be doing it twice at the same time. Or I may have misunderstood of course.
Sounds like an issue with the
PublishedContentContractResolver
and "circular references", it's a big pain in the backside!I assume it's the one from here? https://our.umbraco.com/forum/umbraco-8/98381-serializing-an-publishedcontentmodel-modelsbuilder-model-in-v8#comment-310148
Hmmm, not sure what to suggest, apart from hacking around with the
PublishedContentContractResolver
code. 😕Yes, that's the one.
Funny thing is, it didn't baulk when I returned a string. So that gives me the impression the PublishedContentContractResolver is probably working. However, the UmbracoApiController's default serialisation attempt is probably the one that's blowing, which is why I was hoping to deserialise the PublishedContentContractResolver result back to a string before the UmbracoApiController did it's thing.
As I understand it, this only needs doing to stop certain IPC properties from being serialised.
I agree, it's a PITA. It would be a very elegant solution if you could just call your content and have it sent out as Json. Sounds simple, but..... ;)
Hmmm, if it worked earlier, then you could try this with your original snippet...
Make the return type as
object
:and then when returning, use
JsonConvert.DeserializeObject
to deserialize the string back to an object:BINGO!
I thought I'd tried that earlier but obviously not well enough, lol
That outputs perfectly now.
Thanks very much :)
So for anyone else in this predicament, the final code was:-
Excellent, cool!
is working on a reply...