Resolved JSON to a ListBox not displaying correctly

kwhelchel

Well-known member
Joined
Feb 28, 2020
Messages
53
Programming Experience
Beginner
OK so two things going on here.
First I am getting this when the ListBox items gets added. "OK - System.Collections.Generic.List`1[System.String] - System.Collections.Generic.List`1[ClassLibraryApi.Report]"
Other times it loads nothing and this is the exception it pulls. "System.NullReferenceException: 'Object reference not set to an instance of an object.'"
This section pulls down reports depending on what is selected for the report.

I am thinking both are related to each other but can not figure this out.

Winform code for the listbox

winform:
           {
                ReportViewlistbox.Items.Clear();
                GetReport p = new GetReport();
                var client = new RestClient(p.WebGetReport);
                client.Timeout = -1;
                var request = new RestRequest(Method.POST);
                request.AddHeader("Content-Type", "Value");
                request.AddHeader("Content-Type", "Value");
                var thisJsonStr = "{\"Credentials\":{\"ApiKey\":\"string (CompactGUID)\",\"MerchantID\":\"string\",\"StoreID\":\"string\",\"Username\":\"string\",\"Password\":\"string\"}}", ParameterType.RequestBody);
                request.OnBeforeDeserialization = resp => { resp.ContentType = "application/json"; };
                request.AddParameter("application/json", thisJsonStr, ParameterType.RequestBody);
                IRestResponse response = client.Execute(request);
                var viewreport = Viewreport.FromJson(response.Content);
                ReportViewlistbox.Items.Add($"{viewreport.Result} - {viewreport.ReportHeader} - {viewreport.Reports}");

            }

And this is my class

Class:
public partial class Viewreport
{
    [JsonProperty("Result")]
    public string Result { get; set; }

    [JsonProperty("ReportHeader")]
    public List<string> ReportHeader { get; set; }

    [JsonProperty("Reports")]
    public List<Report> Reports { get; set; }
}

public partial class Report
{
    [JsonProperty("ReportID")]
    [JsonConverter(typeof(ParseStringConverter))]
    public long ReportId { get; set; }

    [JsonProperty("ReportTxt")]
    public List<string> ReportTxt { get; set; }
}

public partial class Viewreport
{
    public static Viewreport FromJson(string json) => JsonConvert.DeserializeObject<Viewreport>(json, ClassLibraryApi.Converter.Settings);
}

public static class Serialize
{
    public static string ToJson(this Viewreport self) => JsonConvert.SerializeObject(self, ClassLibraryApi.Converter.Settings);
}

internal static class Converter
{
    public static readonly JsonSerializerSettings Settings = new JsonSerializerSettings
    {
        MetadataPropertyHandling = MetadataPropertyHandling.Ignore,
        DateParseHandling = DateParseHandling.None,
        Converters =
        {
            new IsoDateTimeConverter { DateTimeStyles = DateTimeStyles.AssumeUniversal }
        },
    };
}

internal class ParseStringConverter : JsonConverter
{
    public override bool CanConvert(Type t) => t == typeof(long) || t == typeof(long?);

    public override object ReadJson(JsonReader reader, Type t, object existingValue, JsonSerializer serializer)
    {
        if (reader.TokenType == JsonToken.Null) return null;
        var value = serializer.Deserialize<string>(reader);
        long l;
        if (Int64.TryParse(value, out l))
        {
            return l;
        }
        throw new Exception("Cannot unmarshal type long");
    }

    public override void WriteJson(JsonWriter writer, object untypedValue, JsonSerializer serializer)
    {
        if (untypedValue == null)
        {
            serializer.Serialize(writer, null);
            return;
        }
        var value = (long)untypedValue;
        serializer.Serialize(writer, value.ToString());
        return;
    }

    public static readonly ParseStringConverter Singleton = new ParseStringConverter();
}

and what postman gets.
Postman:
{
    "Result": "OK",
    "ReportHeader": [
        "     Company: Pizza Schmizza - Pearl",
        "    Run Time: 02/05/21 09:27AM",
        "Reporting On: Current #1"
    ],
    "Reports": [
        {
            "ReportID": "34",
            "ReportTxt": [
                " ",
                "REPORT GROUP: MANDY REPORT",
                "--------------------------------",
                " ",
                "REPORT PRESET: Employee Hours",
                " ",
                " ",
                "EMPLOYEE SHIFTS:",
                " ",
                "    Employee           Job          Time In        Time Out       Reg     OT     Hours     Pay   ",
                "----------------|--------------|---------------|---------------|-------|-------|-------|---------",
                "F, Tanner       |MANAGER       |02/05/21 08:32A|02/05/21 09:27A|   0.93|   0.00|   0.93|    15.14",
                "----------------|--------------|---------------|---------------|-------|-------|-------|---------",
                "                |              |               |               |   0.93|   0.00|   0.93|    15.14"
            ]
        }
    ]
}
 
That's because:
C#:
ReportViewlistbox.Items.Add($"{viewreport.Result} - {viewreport.ReportHeader} - {viewreport.Reports}");
is just a shorthand for:
C#:
string result = viewreport.Result.ToString();
string reportHeader = viewreport.ReportHeader.ToString();
string reports = viewreport.Reports.ToString();
string item = String.Format("{0} - {1} - {2}", result, reportHeader, reports);
ReportViewlistbox.Items.Add(item);

Since C#'s default implementation of ToString() just returns the type name, and since ReportHeader and Reports are both List<string>, then you are getting the result that you are getting.

I don't know why you were expecting C# to expand out the contents of a List<T>. It's not JavaScript.
 
Now try replacing:
C#:
string reportHeader = viewreport.ReportHeader.ToString();
with
C#:
string reportHeader = String.Join(", ", viewreport.ReportHeader);
and see what happens.
 
@Skydiver that worked great for the reportheader line but the reports line still throwing the ClassLibraryApi.Report in the listbos.
Reports line:
     Company: Pizza - Pearl,     Run Time: 02/07/21 07:31AM, Reporting On: Current #1 - ClassLibraryApi.Report

And I have added this into it to break it out line by line in the view. Which works like I want it too.

Break by line:
 string[] values = item.Split(',');

                foreach (string value in values)
                {
                    if (value.Trim() == "")
                        continue;
                    ReportViewlistbox.Items.Add(value.Trim());
                }

and thank you very much
 
This is my ReturnValue ClassLibraryApi.Report[] for this line in it string reports = viewreport.Reports.ToString();
 
*sigh*. You need to write custom code to enumerate each of the Reports inside the list, and the generate a string for each of those Report. To help with that process, read:

 
I have an output from a json file that I have been trying to get to a format I want. The expression I am using looks good on regex101 but when I add it into c# in visual studio I get the red squiggly lines. This being formatted to fit in a listbox and then saved as a text file after. I do have this listed in the using section "using System.Text.RegularExpressions;". I also know I can get the data into a listbox before adding in the regex lines.


Winform code:
                IRestResponse response = client.Execute(request);

                var item = (response.Content);

                string pattern = @"(?-m)(?s)(?<="ReportHeader"\:\[\").+(?=\"\])";
                string input = item;
                MatchCollection collection = Regex.Matches(input, pattern);
                foreach (Match m in collection)
                {
                   ReportViewlistbox.Items.Add(m.Value);
                }

regex code to read:
{"Result":"OK"
"ReportHeader":["     Company: Pizza Schmizza - Pearl"
"    Run Time: 02/12/21 05:17AM"
"Reporting On: Current #1"]
"Reports":[{"ReportID":"34"
"ReportTxt":[" "
"REPORT GROUP: MANDY REPORT"
"--------------------------------"]}]}
 
Quote escape sequence is "" in verbatim strings.
 
Although it looks mangled in your post (copied from some kind of viewer?) the data is probably json and in that case can and should be read structured with for example Json.Net library instead of regex.
 
Well this is the json data here, and I can not for the life of me get anything past the reports line to show with out this error ClassLibraryApi.Report[].
And was instructed to try to use regex to format the output to what I needed. as I only need the report header info and the reporttxt info.
So to be honest I am Very lost here.


Json String:
{
    "Result": "OK",
    "ReportHeader": [
        "     Company: Pizza Schmizza - Pearl",
        "    Run Time: 02/13/21 06:37AM",
        "Reporting On: Current #1"
    ],
    "Reports": [
        {
            "ReportID": "34",
            "ReportTxt": [
                " ",
                "REPORT GROUP: MANDY REPORT",
                "--------------------------------"
            ]
        }
    ]
 
Using Json.Net and JObject to read data untyped:
C#:
var json = JObject.Parse(input);
foreach (var header in json["ReportHeader"])
    Debug.WriteLine(header.ToString().Trim());
foreach (var report in json["Reports"])
    foreach (var txt in report["ReportTxt"])
        Debug.WriteLine(txt);
It is better to create classes for typed access:
C#:
class ReportMain
{
    public string Result { get; set; }
    public string[] ReportHeader{ get; set; }
    public Report[] Reports { get; set; }
}
class Report
{
    public string ReportID { get; set; }
    public string[] ReportTxt { get; set; }
}
Same example using the classes:
C#:
var main = JsonConvert.DeserializeObject<ReportMain>(input);
foreach (var header in main.ReportHeader)
    Debug.WriteLine(header.Trim());
foreach (var report in main.Reports)
    foreach (var txt in report.ReportTxt)
        Debug.WriteLine(txt);
Example output:
Company: Pizza Schmizza - Pearl
Run Time: 02/13/21 06:37AM
Reporting On: Current #1

REPORT GROUP: MANDY REPORT
--------------------------------
 
You already have a thread about this. Merging threads...
 
Back
Top Bottom