web
You’re offline. This is a read only version of the page.
close
Skip to main content

Announcements

No record found.

News and Announcements icon
Community site session details

Community site session details

Session Id :
Finance | Project Operations, Human Resources, ...
Answered

How to access field from a deserialized list

(0) ShareShare
ReportReport
Posted on by 174

How can we get the value from deserialized list in X ?

Like below in C# i could do this but how can I access the any value in x ? It don't even shows me fields of my list to get access.

Code below gives me an error "The array indexing syntax can only be applied to X array types. Use the SetValue and GetValue methods on managed array types."

            defaultException defaultException = JsonConvert::DeserializeObject(response);
            Global::Info(strFmt("exception: %1", defaultException.exception.exceptionDetailList[0].exceptionCode));


public class defaultException
    {
        public KSeF_Exception exception { get; set; }
    }

    public class KSeF_Exception
    {
        public string serviceCtx { get; set; }
        public string serviceCode { get; set; }
        public string serviceName { get; set; }
        public string timestamp { get; set;}
        public string referenceNumber { get; set; }
        public List exceptionDetailList { get; set; }
    }
    public class exceptionDetailList
    {
        public int exceptionCode { get; set; }
        public string exceptionDescription { get; set; }
    }

I have the same question (0)
  • Suggested answer
    Martin Dráb Profile Picture
    239,399 Most Valuable Professional on at

    The error message already told you how you can access a single element - by calling GetValue() method.

    But you usually want to get all elements. If that's the case, you can use an enumerator:

    var enumerator = theList.GetEnumerator();
     
    while (enumerator.MoveNext())
    {
        exceptionDetailList = enumerator.Current;
    }

  • RadekM Profile Picture
    174 on at

    So I need this enumerator anyway... Yet I just realized that I can't even deserialize it.

    defaultException defaultException = JsonConvert::DeserializeObject(response);

    Unable to cast object of type 'Newtonsoft.Json.Linq.JObject' to type 'EDI_KSeF.defaultException'.

  • Verified answer
    Martin Dráb Profile Picture
    239,399 Most Valuable Professional on at

    That's because you're calling the non-generic method (DeserializeObject()), which knows nothing about your custom type. The actual method that your C# code is calling is DeserializeObject<defaultException>(), not DeserializeObject(). C# compiler is able to infer the type and you don't have to specify it, but X++ compiler has no such a feature.

    The easist solution is not calling JsonConvert directly from X++. Instead, create a method in your EDI_KSeF library that accepts a string and return defaultException. Then you'll call the generic method in C# and you won't have to bother with generics in X++.

    Other options exist, of course. For example, you could use the overload of DeserializeObject() that accepts a type as the second argument.

  • RadekM Profile Picture
    174 on at

    Good explanation. I used the overload but im thinking about the first solution.

    Return defaultException would be easy but.. what if I have like 40 other similar objects? Can I manage it all simple by passing the type to one method to get them all? Like something like this?

            public Type testobject(string response, Type type)
            {
                Type mytype = type;
                mytype = JsonConvert.DeserializeObject(response);
                return mytype;
            }

  • Martin Dráb Profile Picture
    239,399 Most Valuable Professional on at

    Now, this isn't possible. The type parameter (T in DeserializeObject<T>) must be know at compile-time, therefore you can't set it at runtime from a method parameter. You would have to implement it like below, but then you would need to call a generic method from X , which won't work (AFAIK). It's the same thing as calling DeserializeObject<T>() directly.

    public T Deserialize(string response)
    {
        return JsonConvert.DeserializeObject(response);
    }

  • RadekM Profile Picture
    174 on at

    Well I did it like this and it works for me at least for now.

    //X  
        authorisationChallengeResponse authorisationChallengeResponse2 = new authorisationChallengeResponse();     
        authorisationChallengeResponse2 = initSession.deserializeResponse(response, authorisationChallengeResponse.GetType());
      
        public System.Object deserializeResponse(str response, Type type)
        {
            System.Object any = new System.Object();
            any = helper.JSONdeserializeAny(response, type);
            
            return any;
        }

    //C#
            public object JSONdeserializeAny(string jSONstring, Type type)
            {
                return JsonConvert.DeserializeObject(jSONstring, type);
            }

  • Verified answer
    Martin Dráb Profile Picture
    239,399 Most Valuable Professional on at

    Then you don't need JSONdeserializeAny() method at all, because it does exactly the same thing as DeserializeObject(). Remember, I suggested either creating a custom method and use the generic method there, or calling the overload of DeserializeObject that accepts a Type as the second parameter.

    Also note that there is no point in creating a new object at line 7, because it's never used and the value gets overwritten at the next line.

    Your code could be reduce to this:

    authorisationChallengeResponse authorisationChallengeResponse2 = new authorisationChallengeResponse();     
    authorisationChallengeResponse2 = JsonConvert.DeserializeObject(response, authorisationChallengeResponse.GetType());

  • RadekM Profile Picture
    174 on at

    Sadly I still strugle to create this enumerators...

            {
            ListEnumerator listenumz;
            List list = new List(Types::String);
            
            list = JsonConvert::DeserializeObject(response, batchInitResponse.GetType());
            listenumz = list.getEnumerator();
            }
    
        public class batchInitResponse
        {
            public string timestamp { get; set;}
            public string referenceNumber { get; set; }
            public packageSignature packageSignature { get; set; }
        }
        
        public class packageSignature
        {
            public string packageName { get; set; }
            public List packagePartSignatureList { get; set; }
        }
    
        public class packagePartSignatureList
        {
            public int ordinalNumber { get; set; }
            public string partFileName { get; set; }
            public string url { get; set; }
            public string method { get; set; }
            public List headerEntryList { get; set; }
        }
    
        public class headerEntryList
        {
            public string key { get; set; }
            public string value { get; set; }
        }

  • RadekM Profile Picture
    174 on at

    How can this possibly work? It just loops endlessly while the value is always null. What to do when in a List is another List? Like above packagePartSignatureList has headerEntryList.

    batchInitResponse batchInitResponse = new batchInitResponse();
    batchInitResponse = JsonConvert::DeserializeObject(batch, batchInitResponse.GetType());
    
    var values = batchInitResponse.packageSignature.packagePartSignatureList;
    var value = values.GetEnumerator();
    
    while (value.MoveNext())
    {
        Global::Info(strFmt(" %1", value.current));
    }

    pastedimage1663233346218v1.png

    pastedimage1663233405827v1.png

  • Martin Dráb Profile Picture
    239,399 Most Valuable Professional on at

    Please use copy&paste to share your code - your screenshot shows different code that you shared above. You could pay attention to letter case when dealing with .NET Interop, despite the fact that X as such is case-insensitive.

    Will you get the same result with this code?

    System.Collections.IEnumerable signatureList = batchInitResponse.packageSignature.packagePartSignatureList;
    System.Collections.IEnumerator enumerator = signatureList.GetEnumerator();
    
    while (enumerator.MoveNext())
    {
        info(strFmt("%1", enumerator.Current));
    }

Under review

Thank you for your reply! To ensure a great experience for everyone, your content is awaiting approval by our Community Managers. Please check back later.

Helpful resources

Quick Links

Introducing the 2026 Season 1 community Super Users

Congratulations to our 2026 Super Stars!

Meet the Microsoft Dynamics 365 Contact Center Champions

We are thrilled to have these Champions in our Community!

Congratulations to the March Top 10 Community Leaders

These are the community rock stars!

Leaderboard > Finance | Project Operations, Human Resources, AX, GP, SL

#1
Giorgio Bonacorsi Profile Picture

Giorgio Bonacorsi 637

#2
André Arnaud de Calavon Profile Picture

André Arnaud de Cal... 594 Super User 2026 Season 1

#3
CP04-islander Profile Picture

CP04-islander 356

Last 30 days Overall leaderboard

Product updates

Dynamics 365 release plans