0

I am relatively new to .Net API development, so apologies if the answer is obvious here.

I have JSON coming in via a request. It is a nested JSON structure with a few subclasses.

I need to get this JSON in and subsequently restructure and distribute it into two, flat classes for storing in two database tables.

What is the best way to go about this? I have used DTOs and Automapper on my path to learning but I am not sure how to go about this with a nested structure.

The incoming JSON looks like this:

{
    "id": xxx,
    "parent_id": xxx,
    "number": "xxx",
    "order_key": "xxx",
    "created_via": "xxx",
    "version": "xxx",
    "status": "xxx",
    "currency": "xxx",
    "date_created": "xxx",
    "date_created_gmt": "xxx",
    "date_modified": "xxx",
    "date_modified_gmt": "xxx",
    "discount_total": "xxx",
    "discount_tax": "xxx",
    "shipping_total": "xxx",
    "shipping_tax": "xxx",
    "cart_tax": "xxx",
    "total": "xxx",
    "total_tax": "xxx",
    "prices_include_tax": xxx,
    "customer_id": xxx,
    "customer_ip_address": "xxx",
    "customer_user_agent": "xxx",
    "customer_note": "",
    "billing": {
    "first_name": "xxx",
    "last_name": "xxx",
    "company": "",
    "address_1": "",
    "address_2": "",
    "city": "",
    "state": "",
    "postcode": "",
    "country": "",
    "email": "xxx",
    "phone": "xxx"
    },
    "shipping": {
    "first_name": "xxx",
    "last_name": "xxx",
    "company": "",
    "address_1": "",
    "address_2": "",
    "city": "",
    "state": "",
    "postcode": "",
    "country": ""
    },
    "payment_method": "xxx",
    "payment_method_title": "xxx",
    "transaction_id": "",
    "date_paid": xxx,
    "date_paid_gmt": xxx,
    "date_completed": xxx,
    "date_completed_gmt": xxx,
    "cart_hash": "xxx",
    "meta_data": [
    {
    "id": xxx,
    "key": "xxx",
    "value": "xxx"
    }
    ],
    "line_items": [
    {
    "id": xxx,
    "name": "xxx",
    "product_id": xxx,
    "variation_id": xxx,
    "quantity": xxx,
    "tax_class": "",
    "subtotal": "xxx",
    "subtotal_tax": "xxx",
    "total": "xxx",
    "total_tax": "xxx",
    "taxes": [],
    "meta_data": [],
    "sku": "",
    "price": xxx
    }
    ],
    "tax_lines": [],
    "shipping_lines": [],
    "fee_lines": [],
    "coupon_lines": [],
    "refunds": [],
    "_links": {
    "self": [
    {
    "href": "xxx"
    }
    ],
    "collection": [
    {
    "href": "xxx"
    }
    ],
    "customer": [
    {
    "href": "xxx"
    }
    ]
    }
    }

Only certain parts of it are relevant. It needs to be mapped into 2 classes as follows:

public class OnlineOrderHeader
    {
        [Key]
        [Required]
        public int OnlineOrderID { get; set; }
        [Required]
        public int AppOrderID { get; set; }
        public int OrderNumber { get; set; }
        [MaxLength(50)]
        public string OrderKey { get; set; }
        [MaxLength(50)]
        public string CreatedVia { get; set; }
        [MaxLength(50)]
        public string Version { get; set; }
        [MaxLength(50)]
        public string Status { get; set; }
        [MaxLength(3)]
        public string Currency { get; set; }
        public DateTime DateCreated { get; set; }
        public DateTime DateModified { get; set; }
        public decimal DiscountTotal { get; set; }
        public decimal DiscountTax { get; set; }
        public decimal CartTax { get; set; }
        public decimal CartTotal { get; set; }
        public int PriceIncludesTax { get; set; } //Check
        public int CustomerID { get; set; }
        [MaxLength(50)]
        public string CustomerFirstName { get; set; }
        [MaxLength(50)]
        public string CustomerLastName { get; set; }
        [MaxLength(50)]
        public string CustomerEmail { get; set; }
        [MaxLength(50)]
        public string CustomerPhone { get; set; }
        [MaxLength(50)]
        public string CustomerEmployeeNo { get; set; }
        [MaxLength(50)]
        public string PaymentMethod { get; set; }
        public int TransactionID { get; set; }
        public DateTime DatePaid { get; set; }
        [MaxLength(500)]
        public string OrderURL { get; set; }
        [MaxLength(500)]
        public string CustomerNotes { get; set; }
        [MaxLength(50)]
        public string CuisineOrderStatus { get; set; }
    }

And

public class OnlineOrderLines
    {
        [Key]
        [Required]
        public int OnlineOrderLineID { get; set; }
        [Required]
        public int AppOrderLineID { get; set; }
        [Required]
        public int ProductID { get; set; }
        [MaxLength(50)]
        public string SKU { get; set; }
        public int Quantity { get; set; }
        public decimal SubTotal { get; set; }
        public decimal SubTotalTax { get; set; }
        public decimal Money { get; set; }
        [MaxLength(100)]
        public string ProductDescription { get; set; }
        [MaxLength(50)]
        public string Category { get; set; }
    }

I am not sure how to get one object with all necessary subclasses using a DTO. Once I have that object, splitting it up into classes should be relatively stratforward, I would assume.

Any tips would be greatly appreciated!

1 Answer 1

1

Firstly, make sure your JSON is valid. The one above isn't. I think the data types need to be more obvious. You have "xxx" and xxx - the latter should be numbers I assume? anyway, I usually just use strings as primitives and worry about the numerical data types later.

Once you have a valid JSON (i.e. take the response string from the request and remove the escape characters - easily done with regex), you can paste it to an online JSON to C# converter (like this one).

This should give you a class structure. You can rename the RootObject to the main name of your API response class. I also check the primitive data types, as those converters are not perfect. As I mentioned above, I usually change the primitives to be strings and deal with data types later, when mapping to view models/entities.

Then, in your API calling class:

  1. Make that API request (i.e httpClient.GetAsync(requestUrl))
  2. Read a response as a string (i.e response.ReadAsStringAsync()
  3. Use Newtonsoft.JSON to deserialize it.
var response = httpClient.GetAsync(requestUrl);
var json = await response.ReadAsStringAsync();
var result = JsonConvert.DeserializeObject<RootObject>(json);

Once you have that RootObject model (which is a raw API response deserialized into an object), you can use the aforementioned Automapper to create OnlineOrderHeader and OnlineOrderLine View Models (simplify/flatten).

Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.