如何使用Swift 4.2解决JSON可解码的坏异常?

时间:2019-02-16 19:15:52

标签: json swift

我的情况是,我试图从RecyclerView.Adapter获取public class RecyclerAdapter extends RecyclerView.Adapter<RecyclerAdapter.MyViewHolder> { private List<String> imagesUrl; private List<String> imageDescription; RecyclerAdapter(List<String> imagesUrl, List<String> imageDescription) { this.imagesUrl = imagesUrl; this.imageDescription = imageDescription; } @NonNull @Override public MyViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int position) { View itemView = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.item, viewGroup, false); return new MyViewHolder(itemView); } @Override public void onBindViewHolder(@NonNull final MyViewHolder myViewHolder, int position) { myViewHolder.textView.setText(imageDescription.get(position)); Picasso.get() .load(imagesUrl.get(position)) .into(new Target() { @Override public void onBitmapLoaded(Bitmap bitmap, Picasso.LoadedFrom from) { myViewHolder.imageView.setImageBitmap(bitmap); myViewHolder.getPalette(); } @Override public void onBitmapFailed(Exception e, Drawable errorDrawable) { myViewHolder.imageView.setImageResource(R.drawable.error); } @Override public void onPrepareLoad(Drawable placeHolderDrawable) { myViewHolder.imageView.setImageResource(R.drawable.placeholder); } }); } @Override public int getItemCount() { return imagesUrl.size(); } class MyViewHolder extends RecyclerView.ViewHolder { private ImageView imageView; private TextView textView; private CardView cardView; MyViewHolder(@NonNull View itemView) { super(itemView); imageView = itemView.findViewById(R.id.imageView); textView = itemView.findViewById(R.id.textView); cardView = itemView.findViewById(R.id.cardView); } private void getPalette() { Bitmap bitmap = ((BitmapDrawable)imageView.getDrawable()).getBitmap(); Palette.from(bitmap).generate(new Palette.PaletteAsyncListener() { @Override public void onGenerated(@Nullable Palette palette) { //assert palette != null; Palette.Swatch swatch = palette.getVibrantSwatch(); //assert swatch != null; textView.setTextColor(swatch.getBodyTextColor()); cardView.setCardBackgroundColor(swatch.getRgb()); } }); } } } 并加载到data中。在JSON期间,我从JSON tableView流程中获得了compile。在我正在使用的JSON响应下面,我无法获得确切的badexception。请提供一些建议

我的JSON响应

decodable

我的东西

issues

我的JSON代码

{
  "status": true,
  "status_code": 1,
  "data": [
    {
      "cat_id": "1",
      "cat_name": "Food",
      "cat_parentid": "2",
      "name": "guru",
      "year": "3000",
      "fullname": {
        "firstname": "jio",
        "lastname": "jack"
      },
      "address": {
        "city": "sanfrancisco",
        "state": "california"
      },
      "ship": {
        "captian": "mojo",
        "time": "12.30.01"
      }
    }
   ]
}

我的问题

issue screen

3 个答案:

答案 0 :(得分:1)

您需要编写结构以完全匹配JSON数据的结构,如下所示:

struct Root: Codable {
    let status: Bool
    let statusCode: Int
    let data: [Datum]

    enum CodingKeys: String, CodingKey {
        case status
        case statusCode = "status_code"
        case data
    }
}

struct Datum: Codable {
    let catID, catName, catParentid, name: String
    let year: String
    let fullname: Fullname
    let address: Address
    let ship: Ship

    enum CodingKeys: String, CodingKey {
        case catID = "cat_id"
        case catName = "cat_name"
        case catParentid = "cat_parentid"
        case name, year, fullname, address, ship
    }
}

struct Address: Codable {
    let city, state: String
}

struct Fullname: Codable {
    let firstname, lastname: String
}

struct Ship: Codable {
    let captian, time: String
}

有了这些,您可以简单地使用JSONDecoder而不需要JSONSerialization

答案 1 :(得分:1)

我从HERE生成了Codable协议,它看起来像:

struct Root: Codable {
    let status: Bool
    let statusCode: Int
    let data: [Datum]

    enum CodingKeys: String, CodingKey {
        case status
        case statusCode = "status_code"
        case data
    }
}

struct Datum: Codable {
    let catID, catName, catParentid, name: String
    let year: String
    let fullname: Fullname
    let address: Address
    let ship: Ship

    enum CodingKeys: String, CodingKey {
        case catID = "cat_id"
        case catName = "cat_name"
        case catParentid = "cat_parentid"
        case name, year, fullname, address, ship
    }
}

struct Address: Codable {
    let city, state: String
}

struct Fullname: Codable {
    let firstname, lastname: String
}

struct Ship: Codable {
    let captian, time: String
}

现在我已经在您的JSON上在Playground上对其进行了检查,如下所示:

let jsonData = """
{
  "status": true,
  "status_code": 1,
  "data": [
    {
      "cat_id": "1",
      "cat_name": "Food",
      "cat_parentid": "2",
      "name": "guru",
      "year": "3000",
      "fullname": {
        "firstname": "jio",
        "lastname": "jack"
      },
      "address": {
        "city": "sanfrancisco",
        "state": "california"
      },
      "ship": {
        "captian": "mojo",
        "time": "12.30.01"
      }
    }
   ]
}
""".data(using: .utf8)!

您可以将其解析为:

let root = try? JSONDecoder().decode(Root.self, from: jsonData)

现在您可以使用

root对象获取数据数组
let content = root?.data //here your crash will resolve

content[Datum]

的一种

答案 2 :(得分:1)

首先使用Gereon提供的结构。

然后将功能替换为

func parseJSON() {

    let url = URL(string: "https://...")

    let task = URLSession.shared.dataTask(with: url!) {(data, response, error) in

        if let error = error { print("returning error", error); return }

        do {
            let result = try JSONDecoder().decode(Root.self, from:data!)
            self.tableArray = result.data
            print(self.tableArray)
        } catch {
            print(error)
            self.tableArray = []
        }
        DispatchQueue.main.async {
            self.tableView.reloadData()
        }

    }
    task.resume()
}