0

I am trying to encode four different arrays into a json format with JSONEncoder, but I am unable to convert the arrays. So, please help me out. I am using swift 4, xcode 9 for iOS 11.

My arrays are:

var timeCart //dynamic data as string
var nameCart //dynamic data as string, ex. ["myNameOne", "myNameTwo", ...]
var quantityCart //dynamic data as Int, ex. [2, 3, 5, ...]
var priceCart //dynamic data as Int, ex. [82, 73, 65, ...]

my structs are:

struct OrderDetailJSON: Encodable {
    let allOrder: [AllOrder]
    let TaxDetials: TaxDetail

    struct AllOrder: Encodable {
        let date_time: String
        let item: String
        let name: String
        let price: String
    }

    struct TaxDetail: Encodable {
        let tax_per: String
        let tax_name: String
    }
}

I am trying to encode it like this, inside a table view

let orderDetailsJSON = OrderDetailJSON(allOrder: [.init(date_time: "\(quantityCart[indexPath.row])", item: "\(quantityCart[indexPath.row])", name: "\(nameCart[indexPath.row])", price: "\(priceCart[indexPath.row])")], TaxDetials: .init(tax_per: defaults.string(forKey: "STORE_TAX")!, tax_name: defaults.string(forKey: "STORE_TAX_NAME")!))
        do {
            let jsonData = try JSONEncoder().encode(orderDetailsJSON)
            let jsonString = String(data: jsonData, encoding: .utf8)
            print("order_details :" + jsonString!)
        }catch{

        }

the output I am getting is:

order_details: {
  "TaxDetials": {
    "tax_per": "5",
    "tax_name": "CGST & SGST"
  },
  "allOrder": [
    {
      "date_time": "2",
      "name": "Manchurian",
      "item": "2",
      "price": "87"
    }
  ]
}order_details: {
  "TaxDetials": {
    "tax_per": "5",
    "tax_name": "CGST & SGST"
  },
  "allOrder": [
    {
      "date_time": "3",
      "name": "Paneer Tikka",
      "item": "3",
      "price": "150"
    }
  ]
}order_details: {
  "TaxDetials": {
    "tax_per": "5",
    "tax_name": "CGST & SGST"
  },
  "allOrder": [
    {
      "date_time": "2",
      "name": "snacks",
      "item": "2",
      "price": "54"
    }
  ]
}

and the output I am expecting is:

order_details: {
  "TaxDetials": {
    "tax_per": "5",
    "tax_name": "CGST & SGST"
  },
  "allOrder": [
    {
      "date_time": "2",
      "name": "Manchurian",
      "item": "2",
      "price": "87"
    },
    {
      "date_time": "3",
      "name": "Paneer Tikka",
      "item": "3",
      "price": "150"
    },
    {
      "date_time": "2",
      "name": "snacks",
      "item": "2",
      "price": "54"
    }
  ]
}
Dávid Pásztor
  • 51,403
  • 9
  • 85
  • 116
Neck
  • 611
  • 1
  • 7
  • 21

1 Answers1

0

There's nothing wrong with your struct declarations (other than the fact that you should conform to the Swift naming convention, which is lowerCamelCase for variable names - taxPer instead of tax_per, etc. and that your property names don't use the correct plural/singular forms).

The issue is that you are defining an OrderDetailJSON instance for each table view cell, while it seems that your TaxDetails should be the same for all cells in the table and you actually want to create a single OrderDetailJSON instance whose allOrder array property contains one AllOrder instance for each table view cell. You'll need to change the allOrder property to mutable for this to work.

class YourTableViewController: UITableViewController {
    var orderDetails: OrderDetailJSON
    ...
    // You might need to use a different tableView function depending on your exact needs
    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        orderDetails.allOrder[indexPath.row] = AllOrder(date_time: "\(quantityCart[indexPath.row])", item: "\(quantityCart[indexPath.row])", name: "\(nameCart[indexPath.row])", price: "\(priceCart[indexPath.row])")
    }
}

You need to make sure that orderDetails is initialized with the correct TaxDetails and that you preallocate the same number of elements to allOrder as many table view cells you'll have. You only need to convert the orderDetails to JSON once all cells have been filled up with information, you don't need to do it on a cell by cell basis.

Dávid Pásztor
  • 51,403
  • 9
  • 85
  • 116
  • it's throwing nil. – Neck May 26 '18 at 11:23
  • What's throwing `nil`? Since I've only included a skeleton code, please update your question with the code you use currently and pinpoint which line produces `nil`. – Dávid Pásztor May 26 '18 at 14:36
  • orderDetailJSON.allOrder[indexPath.row] = AllOrder(date_time: "\(quantityCart[indexPath.row])", item: "\(quantityCart[indexPath.row])", name: "\(nameCart[indexPath.row])", price: "\(priceCart[indexPath.row])")... this line giving an error saying "found nil while unwrapping an optional value", I am using it inside tableView's 'cellForRowAt' function. @david – Neck May 28 '18 at 04:52
  • @Neck then it seems you didn't actually initialize `orderDetails`. You should do that in an initializer or `viewDidLoad` depending on where exactly your data is coming from. – Dávid Pásztor May 28 '18 at 10:05