0

How can i decode this string

"<div id=\"readability-page-1\" class=\"page\">test<div>"

I receive this object from an api and i want to decode it into a struct:

{
 "id": 5,
 "title": "iOS and iPadOS 14: The MacStories Review",
 "content": "<div id=\"readability-page-1\" class=\"page\">test<div>"
}
struct ArticleModel: Codable, Identifiable {
 let id: Int
 let title: String
 let content: String
}

However this throws the error

debugDescription : "The given data was not valid JSON."
 ▿ underlyingError : Optional<Error>
 - some : Error Domain=NSCocoaErrorDomain Code=3840 "Badly formed object around line 45, column 25." UserInfo={NSDebugDescription=Badly formed object around line 45, column 25., NSJSONSerializationErrorIndex=1437}

How can i escape the special characters " ?

I want to display the string in a view as an attributed string.

Testing via playground

import UIKit
let json = """
{
 "id": 5,
 "title": "iOS and iPadOS 14: The MacStories Review",
 "content": "<div id=\"readability-page-1\" class=\"page\">test<div>"
}
"""
struct ArticleModel: Codable, Identifiable {
 let id: Int
 let title: String
 let content: String
}
let jsonData = json.data(using: .utf8)!
let decoder = JSONDecoder()
decoder.keyDecodingStrategy = .convertFromSnakeCase
let article = try decoder.decode(ArticleModel.self, from: jsonData)
print(article)
asked Dec 21, 2021 at 17:06
4
  • 1
    Talk to the API provider, their JSON is invalid and unparseable Commented Dec 21, 2021 at 17:20
  • Updated the json since i saw StackOverflow messed up my json to remove everything behind \n. The json i provide now is validate but not decodable by swift Commented Dec 21, 2021 at 18:08
  • 1
    your JSON seems valid for me Commented Dec 21, 2021 at 18:33
  • Do you NEED the json to be in a string? you can save it in a file Commented Dec 21, 2021 at 18:58

2 Answers 2

1

The JSON seems incorrect. There seems to be a missing " at the end of the value of "content":.

EDIT:

After your update, I took another look. You need to escape double quotes in a string. Weirdly enough, in this case (when the JSON is in a multi-line string), you need to escape the escaping character as well (i.e. \\) to decode the JSON properly and get a string you can work with.

Example:

import UIKit
let json = """
{
 "id": 5,
 "title": "iOS and iPadOS 14: The MacStories Review",
 "content": "<div id=\\"readability-page-1\\" class=\\"page\\">test<div>"
}
"""
struct ArticleModel: Codable, Identifiable {
 let id: Int
 let title: String
 let content: String
}
let jsonData = json.data(using: .utf8)!
let article = try JSONDecoder().decode(ArticleModel.self, from: jsonData)
print(article) // ArticleModel(id: 5, title: "iOS and iPadOS 14: The MacStories Review", content: "<div id=\"readability-page-1\" class=\"page\">test<div>")

By the way, https://app.quicktype.io/ is a great tool to get decoders (and encoders) for your JSON.

answered Dec 21, 2021 at 17:16
Sign up to request clarification or add additional context in comments.

4 Comments

Thanks, i see StackOverflow messes with the code i wrote and removed everything behind \n. simplified the json so it displays correctly.
@andredewaard I have updated my answer after your changes.
The \\ is only needed when you have the json string in code, the original json does not need to be changed.
@JoakimDanielson True, this is when you use these multi-line literal strings.
1

You can use single quotes to make the json look better, and it would still be a valid HTML

let realJson = "{\"id\": 5,\"title\": \"iOS and iPadOS 14: The MacStories Review\",\"content\": \"<div id='readability-page-1' class='page'>test<div>\"}"
func parseJson(for json: String?) -> ArticleModel? {
 guard let json = json, let jsonData = json.data(using: .utf8) else { return nil }
 let decoder = JSONDecoder()
 decoder.keyDecodingStrategy = .convertFromSnakeCase
 guard let article = try? decoder.decode(ArticleModel.self, from: jsonData) else { return nil }
 return article
}
let article = parseJson(for: realJson)
print(article?.id ?? 0)
struct ArticleModel: Codable, Identifiable {
 let id: Int
 let title: String
 let content: String
}

Imo. For a more readable code, maybe having the JSON in a .txt file and reading it from there, would be better

Cheers 👍

answered Dec 21, 2021 at 19:09

1 Comment

Straight up facts no 🧢

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.