Copied to clipboard

Flag this post as spam?

This post will be reported to the moderators as potential spam to be looked at


  • Sandra26 15 posts 115 karma points
    Sep 12, 2019 @ 15:02
    Sandra26
    0

    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.

  • louisjrdev 107 posts 344 karma points c-trib
    Sep 12, 2019 @ 15:44
    louisjrdev
    0

    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.

  • Steven Baker 7 posts 77 karma points
    Sep 12, 2019 @ 15:47
    Steven Baker
    0

    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

  • Lee Kelleher 4020 posts 15802 karma points MVP 13x admin c-trib
    Sep 12, 2019 @ 16:00
    Lee Kelleher
    102

    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...

    @{
        var settings = new JsonSerializerSettings
        {
            ContractResolver = new PublishedContentContractResolver()
        };
        var serialized = JsonConvert.SerializeObject(l, Formatting.Indented, settings);
    }
    

    Hope this helps.

    Cheers,
    - Lee

  • Sandra26 15 posts 115 karma points
    Sep 16, 2019 @ 09:54
    Sandra26
    0

    Thank you very much for your answers, they were really helpful. You all have a nice day , Sandra

  • Craig100 1136 posts 2523 karma points c-trib
    Mar 26, 2021 @ 13:36
    Craig100
    0

    Hi,

    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:

    "[\r\n  {\r\n    \"Area\": 1,\r\n    \"Some_Id\": 3,\r\n    \"Column\": 1,\r\n    \"Common_Name\": \"Some name\",\r\n    etc.
    

    Any advice would be appreciated.

    Craig

  • Lee Kelleher 4020 posts 15802 karma points MVP 13x admin c-trib
    Mar 26, 2021 @ 14:19
    Lee Kelleher
    1

    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 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()
                }
            };
        }
    }
    

    Hope this helps?

    Cheers,
    - Lee

  • Craig100 1136 posts 2523 karma points c-trib
    Mar 26, 2021 @ 14:32
    Craig100
    0

    Thanks Lee,

    I'm afraid that resulted in :-

    "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.

  • Lee Kelleher 4020 posts 15802 karma points MVP 13x admin c-trib
    Mar 26, 2021 @ 14:46
    Lee Kelleher
    0

    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. 😕

  • Craig100 1136 posts 2523 karma points c-trib
    Mar 26, 2021 @ 14:53
    Craig100
    0

    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..... ;)

  • Lee Kelleher 4020 posts 15802 karma points MVP 13x admin c-trib
    Mar 26, 2021 @ 14:58
    Lee Kelleher
    1

    Hmmm, if it worked earlier, then you could try this with your original snippet...

    Make the return type as object:

    public object GetAllThings()
    

    and then when returning, use JsonConvert.DeserializeObject to deserialize the string back to an object:

    return JsonConvert.DeserializeObject(serialized);
    
  • Craig100 1136 posts 2523 karma points c-trib
    Mar 26, 2021 @ 15:01
    Craig100
    1

    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:-

    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);
        }
    }
    
  • Lee Kelleher 4020 posts 15802 karma points MVP 13x admin c-trib
    Mar 26, 2021 @ 15:03
    Lee Kelleher
    0

    Excellent, cool!

Please Sign in or register to post replies

Write your reply to:

Draft