C# Json Help Please

Daryl

I am creating a integration to a 3rd party logistics company utilizing their REST calls and I am struggling trying to create the body. I followed what you shown above and was wondering if you could give tis a quick review and let me know what I may be doing wrong. I appreciate any feedback.


body.paymentType = "PREPAID";
body.billToId = 12345;
body.includeGauranteeRates = true;

body.origin.locationId = 12345;
body.origin.zip = "12345";

body.destination.locationId = 0;
body.destination.zip = "708416";

body.feetOfTrailer = 0;

//line items
dynamic lineitems = new Newtonsoft.Json.Linq.JArray();
dynamic lineitem = new Newtonsoft.Json.Linq.JObject();

lineitem.weight = 57;
lineitem.freightClass = "300";
lineitem.length = 39M;
lineitem.width = 45M;
lineitem.height = 51M;
lineitem.isStackable = false;
lineitem.isHazMat = false;

lineitems.Add(lineitem);
body.Add(lineitems);

//accesorial services
dynamic accessorialServices = new Newtonsoft.Json.Linq.JObject();
dynamic accessorials = new Newtonsoft.Json.Linq.JArray();
dynamic accessorial = new Newtonsoft.Json.Linq.JObject();
accessorial.code = string.Empty;
accessorial.name = string.Empty;

accessorials.Add(accessorial);

body.accessorialServices.Add(accessorial);
body.accessorialServices.codCheckType = "CERTIFIED";
body.accessorialServices.codPaymentType = "COLLECT";
body.accessorialServices.codAmount = 0;

Scott

What errors are you getting?

At a glance, it looks like the handling of arrays isn’t right, but it would help to know specifically what you’re seeing that needs solving.

Show us what your Json is supposed ti look like and we’ll guide you from there.

Here is the body I am trying to create

 {
  "paymentType": "PREPAID",
  "billToID": 0,
  "includeGuaranteedRates": true,
  "origin": {
    "locationID": 0,
    "zip": "string"
  },
  "destination": {
    "locationID": 0,
    "zip": "string"
  },
  "feetOfTrailer": 0,
  "lineItems": [
  {}
  ],
  "accessorialServices": {
    "accessorials": [
      {
      "code": "string",
      "name": "string"
      }
    ],
  "codCheckType": "CERTIFIED",
  "codPaymentType": "COLLECT",
  "codAmount": 0
  }
}

Thanks for looking

You can do this a bunch of ways.

Here is one:

//using Newtonsoft.Json;
//using Newtonsoft.Json.Linq;

        string paymentType = "PREPAID";
        int billToID = 12345;
        int feetOfTrailer = 0;

        JObject paymentOrigin = new JObject
        {
                ["locationID"] = 0,
                ["zip"] = "71454"
        };

        JObject destination= new JObject
        {
                ["locationID"] = 0,
                ["zip"] = "90210"
        };

        string accessorialCode = "hello";
        string accessorialName = "there";
        string codCheckType = "CERTIFIED";
        string codPaymentType = "COLLECT";
        decimal codAmount = 0;

        JObject accessorialServices = new JObject
        {
            ["accessorials"] = new JArray()
            {
                new JObject
                {
                    ["code"] = accessorialCode,
                    ["name"] = accessorialName
                }
            },
            ["codCheckType"] = codCheckType,
       		["codPaymentType"] = codPaymentType,
		    ["codAmount"] = codAmount
        };

        JObject objectWeAreMaking = new JObject
        {
            ["paymentType"] = paymentType,
            ["billToID"] = billToID,
            ["includeGuaranteedRates"] = true,
            ["origin"] = paymentOrigin,
            ["destination"] = destination,
            ["feetOfTrailer"] = feetOfTrailer,
            ["lineItems"] = new JArray(),
            ["accessorialServices"] = accessorialServices
        };

Output:

{
  "paymentType": "PREPAID",
  "billToID": 12345,
  "includeGuaranteedRates": true,
  "origin": {
    "locationID": 0,
    "zip": "71454"
  },
  "destination": {
    "locationID": 0,
    "zip": "90210"
  },
  "feetOfTrailer": 0,
  "lineItems": [],
  "accessorialServices": {
    "accessorials": [
      {
        "code": "hello",
        "name": "there"
      }
    ],
    "codCheckType": "CERTIFIED",
    "codPaymentType": "COLLECT",
    "codAmount": 0.0
  }
}
2 Likes

Kevin,

Thank you, I will give this a go. I really appreciate the clarity and the code.

Scott

2 Likes

Another thing you can do is create a class in c# that you can load an epicor data table or result to so that you have strongly defined fields/objects in the class. Then you can serialize the class into a json object using newtonsoft.

I’ve found it makes checking for null data and invalid casts down the line a lot cleaner.

1 Like

I started to suggest he could make a class, but I assumed he was working in a BPM or Function or something.

2 Likes
public class SharedLtLBookingResponseObject
{
    public string id { get; set; }
    public DateTime createdDate { get; set; }
    public bool archived { get; set; }
    public string direction { get; set; }
    public DateTime pickupDate { get; set; }
    public string status { get; set; }
    public Billto billTo { get; set; }
    public string[] accessorials { get; set; }
    public Origin origin { get; set; }
    public Destination destination { get; set; }
    public Tracking tracking { get; set; }
    public File[] files { get; set; }
    public Invoice invoice { get; set; }
    public string[] shareShipmentEmails { get; set; }
    public string quotedBy { get; set; }
    public string bookedBy { get; set; }
    public string bolNum { get; set; }
    public string paymentTerms { get; set; }
    public Item[] items { get; set; }
    public Rate rate { get; set; }
    public Dispatch dispatch { get; set; }
}

public class Billto
{
    public string company { get; set; }
    public string address { get; set; }
    public string address2 { get; set; }
    public string city { get; set; }
    public string state { get; set; }
    public string postalCode { get; set; }
    public string country { get; set; }
    public string contactName { get; set; }
    public string contactEmail { get; set; }
    public string contactPhone { get; set; }
}

public class Origin
{
    public string company { get; set; }
    public string address { get; set; }
    public string address2 { get; set; }
    public string city { get; set; }
    public string state { get; set; }
    public string postalCode { get; set; }
    public string country { get; set; }
    public string shipType { get; set; }
    public string contactName { get; set; }
    public string contactPhone { get; set; }
    public string contactEmail { get; set; }
    public string referenceNumber { get; set; }
    public string instructions { get; set; }
    public string dockHoursOpen { get; set; }
    public string dockHoursClose { get; set; }
}

public class Destination
{
    public string company { get; set; }
    public string address { get; set; }
    public string address2 { get; set; }
    public string city { get; set; }
    public string state { get; set; }
    public string postalCode { get; set; }
    public string country { get; set; }
    public string shipType { get; set; }
    public string contactName { get; set; }
    public string contactPhone { get; set; }
    public string contactEmail { get; set; }
    public string referenceNumber { get; set; }
    public string instructions { get; set; }
    public string dockHoursOpen { get; set; }
    public string dockHoursClose { get; set; }
}

public class Tracking
{
    public string status { get; set; }
    public string summary { get; set; }
    public DateTime lastUpdatedDate { get; set; }
    public DateTime pickupDateActual { get; set; }
    public DateTime deliveryDateEstimate { get; set; }
    public DateTime deliveryDateActual { get; set; }
    public History[] history { get; set; }
}

public class History
{
    public string status { get; set; }
    public string summary { get; set; }
    public DateTime createdDate { get; set; }
}

public class Invoice
{
    public DateTime createdDate { get; set; }
    public double invoiceAmount { get; set; }
    public string invoiceNumber { get; set; }
    public double disputedAmount { get; set; }
    public Payment[] payments { get; set; }
}

public class Payment
{
    public double amount { get; set; }
    public bool remitted { get; set; }
}

public class Rate
{
    public double total { get; set; }
    public int days { get; set; }
    public string serviceType { get; set; }
    public string serviceOption { get; set; }
    public string serviceDescription { get; set; }
    public string carrierId { get; set; }
    public string carrier { get; set; }
    public string carrierCode { get; set; }
    public int time { get; set; }
    public bool rural { get; set; }
    public Charge[] charges { get; set; }
    public bool interline { get; set; }
    public bool daysPlus { get; set; }
    public string mode { get; set; }
    public string paymentTerms { get; set; }
    public string provider { get; set; }
    public string providerCode { get; set; }
    public DateTime createdDate { get; set; }
    public string quoteNum { get; set; }
}

public class Charge
{
    public string name { get; set; }
    public double amount { get; set; }
    public string providerDetail { get; set; }
    public string code { get; set; }
}

public class Dispatch
{
    public string carrierId { get; set; }
    public string carrier { get; set; }
    public string carrierCode { get; set; }
    public bool schedulePickup { get; set; }
    public string bolStatus { get; set; }
    public string pickupNum { get; set; }
    public string proNum { get; set; }
}

public class File
{
    public string type { get; set; }
    public string subtype { get; set; }
    public DateTime uploadDate { get; set; }
    public string url { get; set; }
}

public class Item
{
    public string description { get; set; }
    public int weight { get; set; }
    public int freightClass { get; set; }
    public int length { get; set; }
    public int width { get; set; }
    public int height { get; set; }
    public string package { get; set; }
    public int pieces { get; set; }
    public string nmfc { get; set; }
    public bool hazardous { get; set; }
    public Hazard hazard { get; set; }
    public int saidToContain { get; set; }
    public string saidToContainPackagingType { get; set; }
    public bool stackable { get; set; }
}

public class Hazard
{
    public string hazmatId { get; set; }
    public string hazardClass { get; set; }
    public string hazardSubClass1 { get; set; }
    public string hazardSubClass2 { get; set; }
    public string packingGroup { get; set; }
    public string specialPermit { get; set; }
}


public class FreightViewResponseErrorMessage
{
    public string error { get; set; }
    public string errorType { get; set; }
    public string message { get; set; }
}

Here’s the desrialization:

using (var reader = new StreamReader(response.GetResponseStream()))

								{
										/*Here we are converting the booking response into a class so that we can access the properties of it like:
										 the booking ID, the proNum, and the URL for any labels. We are also checking to make sure the result was a success.*/
										SharedLtLBookingResponseObject BookingResponse = new SharedLtLBookingResponseObject();
								    	var jsonResult = reader.ReadToEnd();
									
										BookingResponse = JsonConvert.DeserializeObject<SharedLtLBookingResponseObject>(jsonResult);
2 Likes

when_you_assume

2 Likes

Assumption correct, inside a function. Cannot create a Class inside a function

And Scott if you have an example of the JSON you can copy it into a C# visual studio project and say, “create as class,” and then you’ll have somethign you can copy and paste into your form customization if you are doing it in classic forms.

But if you’re doing it in BPM or function for kinetic then I think there’s no luck using classes yet, right @klincecum ?

Paste JSON or XML as classes - Visual Studio (Windows) | Microsoft Learn

Not directly, no.

Like Kevin says, not directly. IF one follows some decoupling practices, there would be a facade pattern between the 3rd party and Kinetic. In that endpoint, you’d have the full freedom to create a validation class - which IS a good idea. This level of abstraction could also help hide API-Keys from the client to provide a more secure integration - a backend for front end. It would also place a buffer between changes in the APIs of each party.

Getting API security right - Philippe De Ryck - NDC London 2023 - YouTube

Securing SPAs and Blazor Applications using the BFF (Backend for Frontend) Pattern - Dominick Baier - YouTube

1 Like

Oooohhhh reading material!

Read Beauty And The Beast GIF by Disney

Apparently I’m dumb.

commercial space jam GIF

Not this video either…although it’s also good. It doesn’t take an astrophysicist to…wait a minute. :thinking:

Queen - You’re My Best Friend (Official Video) - YouTube

1 Like

All joking aside, when people say “create a class in C#” and they’re talking about Epicor, where are they talking about creating that?

The only place that I know of that you can do that is in a classic customization. Unless you have the SDK and can make your own datasets.

1 Like

Classic customization which yeah, I don’t want to do anymore/am not doing anymore in the kinetic environments.