Resolved Nested Classes with Arrays, Part 2

RobertbNZ

Active member
Joined
Jun 26, 2020
Messages
34
Programming Experience
Beginner
Skydiver, this is a follow-on from my previous query, I'm now trying to handle a response containing 10 occurrences of the Employee record. I'm having some challenges bridging the COBOL world where Records and Fields map an area of memory, and the .NET world of reference and value classes. How do I get data into the array class JZ_Employee?

The Response classes are defined like this: -
C#:
namespace MyJSv
{
    public class ResponseJSPG2A
    {
        public class JSPG2AResponse_
        {
            public class OJSPG2A_
            {
...
                public int JZ_Employee_BrowseCount { get; set; }
                // and more scalar classes,
                public class JZ_Employee_
                {
                    public string JZ_Employee_NthReturnCode { get; set; }
                    public string EMPNO { get; set; }
                    // and more classes within the Employee record
                }
                public JZ_Employee_[] JZ_Employee { get; } = new JZ_Employee_[10];
            }
            public OJSPG2A_ OJSPG2A { get; } = new OJSPG2A_ ();
        }
        public JSPG2AResponse_ JSPG2AResponse { get; } = new JSPG2AResponse_ ();
    }
}

The point of this is that it will be much quicker to return a chunk of records in one request/response, and only go back to the service when the next chunk is required. The first test however reads Employee by its 1ry key, and should return only one record and 9 "empty" JSON records.

A ReadyAPI test reading Employee by its 1ry key shows that 10 occurrences of JZ-Employee are returned, with data in the first and empty JSON in the rest. This is correct. Next step: handle this with my own code.

With the same test parameters, method JSPG2AClient.ReqestRespond sends the request to the service, which responds through code: -
C#:
                if (response.IsSuccessStatusCode)
                {
                    Response = JsonConvert.DeserializeObject<ResponseJSPG2A>(result);
                    AssignResponseToProperties(true);
                    return true;
                }

AssignResponseToProperties fails on the first statement attempting to assign an array value: -
C#:
        _JZ_Employee_NthReturnCode = Response.JSPG2AResponse.OJSPG2A.JZ_Employee[EmployeeSub].JZ_Employee_NthReturnCode;

Debugging shows that although the scalar classes all have values, the array classes are all null

Snap1.jpg


The response is created by the statement above
C#:
Response = JsonConvert.DeserializeObject<ResponseJSPG2A>(result);

Result is properly-formed JSON, containing 10 occurrences of JZ_Employee with data in the first and empty JSON in the rest. Exactly as I had expected. I saved and displayed the JSON, it shows
JSON:
{
  "JSPG2AResponse": {
    "OJSPG2A": {
...
      "JZ_Employee_BrowseCount": 0,
     // more scalar fields
      "JZ_Employee": [
        {
          "JZ_Employee_NthReturnCode": "U",
          "EMPNO": "000060",
          // other fields of first Employee
        },
        {
          "JZ_Employee_NthReturnCode": "",
          "EMPNO": "000000",
...       // rest of initialized fields
        },
        //  Another 8 empty occurrences
      ]
    }
  }
}

This StackOverflow article suggests that I need to use <List<JZ_Employee_>> to deserialize the array class, but of course that's only part of <ResponseJSPG2A> and so of course <List<ResponseJSPG2A>> is not valid. Help.

Thank you, Robert.
 

RobertbNZ

Active member
Joined
Jun 26, 2020
Messages
34
Programming Experience
Beginner
Stack Overflow has now shown me how to resolve this. The getter for JZ-Employee is changed from
C#:
                public JZ_Employee_[] JZ_Employee { get; } = new JZ_Employee_[10];
to
C#:
                public List<JZ_Employee_> JZ_Employee { get; private set; } = new List<JZ_Employee_>();
For this to be valid this needs
C#:
using System.Collections.Generic;

All very simple, now that I've been shown what to do :)
 

Skydiver

Staff member
Joined
Apr 6, 2019
Messages
2,392
Location
Chesapeake, VA
Programming Experience
10+
You just need:
C#:
public List<JZ_Employee_> JZ_Employee { get; } = new List<JZ_Employee_>();
If you are only ever going to create the list once per instance during construction. If you will be dynamically replacing the list after construction, then the private set will be useful to show others reading your code that you intend to replace the list later.
 

RobertbNZ

Active member
Joined
Jun 26, 2020
Messages
34
Programming Experience
Beginner
Thanks @Skydiver, I'll bear that in mind as I develop the logic of the interface. It's a useful comment as it made me think about my program in a new way.

In my test data, an SQL enquiry for WorkDept="D11" returns 17 records Every request/response takes a second or so, so it's a slow process to look at all the records in WorkDept="D11" in turn if you have to use a request/response for every record, as in my first program (JSPG2). The current experiments are looking a returning several records at a time so that, once I've got a bunch of records, I can scroll forwards and back simply by setting an array index. The C# array is completely regenerated with each request/response, so either solution would do when the maximum number of records that could theoretically be returned (17) is <= the maximum number of records that the COBOL web service allows.

However I can't guarantee that this will always be the case, so I have to develop logic that might be just setting an array index in the bunch of records already returned, or might require another request/response. I need an approach that will allow me to add to the list, so private set sounds useful. Thank you for this suggestion.
 
Top Bottom