Home > other >  Web API how to parse unicode json
Web API how to parse unicode json

Time:09-12

I'm really confused by API of web service

Some blocks of data has a format like that:

"ja": "犯罪\u8005の子孫た\u3061が暮\u3089\u3059スラム\u8857\u3002\u5883界線の\u5411\u3053\u3046の人\u3005か\u3089は「族民」\u3068\u3055\u3052\u3059まれ\u3001差\u5225\u3092受\u3051\u3066\u3044た\u3002孤\u5150\u3060\u3063た少年・ルドは\u3001育\u3066の親\u3067\u3042るレグト\u3068\u5171にスラム\u8857に住み\u3001常人離れ\u3057た身体能力\u3092武\u5668に生計\u3092立\u3066\u3066\u3044た\u3002\u3060が\u3042る日\u3001身に覚\u3048のな\u3044罪\u3092\u7740せ\u3089れ\u3001スラムの人\u3005\u3067\u3055\u3048\u6050れる「\u5948落」\u3078\u3068落\u3068\u3055れ\u3066\u3057ま\u3046\u2026\u2026\u3002"

I realized that Swift do not work with those format. But I really don't know in what step I should convert this

My parse func:

URLSession
    .shared
    .dataTask(with: request) { data, response, error in
        if let data = data {
            do {
                if let sanitisedData = String(data: data, encoding: .utf8)!.map({ String($0) }).filter({ $0 != "\\" }).joined(separator: "").replacingOccurrences(of: "U(.*?)", with: "\\\\u$1", options: .regularExpression).data(using: .utf8) {
                    let decoder = JSONDecoder()
                    
                    let decodedResponse = try decoder.decode(Welcome.self, from: sanitisedData)
                    
                    DispatchQueue.main.async {
                        self.data = decodedResponse
                    }
                }
            } catch let jsonError as NSError {
                print("JSON Decode Failed: \(jsonError.localizedDescription)")
            }
            
            return
        }
    }
    .resume()

Output:

JSON Decode Failed: The data couldn’t be read because it isn’t in the correct format.

I tried to convert this data to string and that's the result:

犯罪u8005の子孫たu3061が暮u3089u3059スラムu8857u3002u5883界線のu5411u3053u3046の人u3005かu3089は「族民」u3068u3055u3052u3059まれu3001差u5225u3092受u3051u3066u3044たu3002孤u5150u3060u3063た少年・ルドはu3001育u3066の親u3067u3042るレグトu3068u5171にスラムu8857に住みu3001常人離れu3057た身体能力u3092武u5668に生計u3092立u3066u3066u3044たu3002u3060がu3042る日u3001身に覚u3048のなu3044罪u3092u7740せu3089れu3001スラムの人u3005u3067u3055u3048u6050れる「u5948落」u3078u3068落u3068u3055れu3066u3057まu3046u2026u2026u3002

Example of response:

{
  "result": "ok",
  "response": "collection",
  "data": [
    {
      "id": "f2e906bb-8329-4f93-af70-b6344f18aa07",
      "type": "manga",
      "attributes": {
        "title": {
          "en": "This players think i\u2019m one of them"
        },
        "altTitles": [
          {
            "ru": "Э\u0442\u0438 \u0438\u0433\u0440ок\u0438 \u0434\u0443м\u0430ю\u0442, \u0447\u0442о я о\u0434\u0438н \u0438\u0437 н\u0438\u0445"
          }
        ],
        "description": {
          "en": "I am the Dark Lord. The one who united the demons. One who wields limitless power and might. The one who has had enough of it all.\n\nThese people have attacked our lands again!\n\nFor a hundred years now.... vile players have attacked our hellish lands, mercilessly plundering and killing peaceful demons.\n\nToday I will become human, infiltrate the ranks of humanity and destroy their rotten system from within... while these players think I'm one of them.",
          "ru": "Я - \u0422\u0435мны\u0439 по\u0432\u0435л\u0438\u0442\u0435ль. \u0422о\u0442, к\u0442о о\u0431ъ\u0435\u0434\u0438н\u0438л \u0434\u0435моно\u0432. \u0422о\u0442, к\u0442о о\u0431л\u0430\u0434\u0430\u0435\u0442 \u0431\u0435\u0441кон\u0435\u0447но\u0439 \u0432л\u0430\u0441\u0442ью \u0438 \u0441\u0438ло\u0439. \u0422о\u0442, ком\u0443 \u0432\u0441\u0435 э\u0442о н\u0430\u0434о\u0435ло.\n\nЭ\u0442\u0438 лю\u0434\u0438 \u0432 о\u0447\u0435\u0440\u0435\u0434но\u0439 \u0440\u0430\u0437 н\u0430п\u0430л\u0438 н\u0430 н\u0430\u0448\u0438 \u0437\u0435мл\u0438!\n\n\u0412о\u0442 \u0443\u0436\u0435 \u0441о\u0442ню л\u0435\u0442\u2026. М\u0435\u0440\u0437к\u0438\u0435 \u0438\u0433\u0440ок\u0438 \u0430\u0442\u0430к\u0443ю\u0442 н\u0430\u0448\u0438 \u0430\u0434\u0441к\u0438\u0435 \u0437\u0435мл\u0438, \u0431\u0435\u0441по\u0449\u0430\u0434но \u0433\u0440\u0430\u0431я \u0438 \u0443\u0431\u0438\u0432\u0430я м\u0438\u0440ны\u0445 \u0434\u0435моно\u0432.\n\n\u0412н\u0435\u0441\u0438\u0442\u0435 Э\u0422О!\n\n\u0421\u0435\u0433о\u0434ня я \u0441\u0442\u0430н\u0443 \u0447\u0435ло\u0432\u0435ком, п\u0440о\u0431\u0435\u0440\u0443\u0441ь \u0432 \u0440я\u0434ы \u0447\u0435ло\u0432\u0435\u0447\u0435\u0441\u0442\u0432\u0430 \u0438 \u0443н\u0438\u0447\u0442о\u0436\u0443 \u0438\u0445 п\u0440о\u0433н\u0438\u0432\u0448\u0443ю \u0441\u0438\u0441\u0442\u0435м\u0443 \u0438\u0437н\u0443\u0442\u0440\u0438... пок\u0430 э\u0442\u0438 \u0438\u0433\u0440ок\u0438 \u0434\u0443м\u0430ю\u0442, \u0447\u0442о я о\u0434\u0438н \u0438\u0437 н\u0438\u0445."
        },
        "isLocked": false,
        "links": {
          "raw": "https://remanga.org/manga/this-players-think-im-one-of-them?subpath=about"
        },
        "originalLanguage": "ru",
        "lastVolume": "",
        "lastChapter": "",
        "publicationDemographic": "seinen",
        "status": "ongoing",
        "year": 2022,
        "contentRating": "suggestive",
        "tags": [
          {
            "id": "36fd93ea-e8b8-445e-b836-358f02b3d33d",
            "type": "tag",
            "attributes": {
              "name": {
                "en": "Monsters"
              },
              "description": [],
              "group": "theme",
              "version": 1
            },
            "relationships": []
          },
          {
            "id": "391b0423-d847-456f-aff0-8b0cfc03066b",
            "type": "tag",
            "attributes": {
              "name": {
                "en": "Action"
              },
              "description": [],
              "group": "genre",
              "version": 1
            },
            "relationships": []
          },
          {
            "id": "39730448-9a5f-48a2-85b0-a70db87b1233",
            "type": "tag",
            "attributes": {
              "name": {
                "en": "Demons"
              },
              "description": [],
              "group": "theme",
              "version": 1
            },
            "relationships": []
          },
          {
            "id": "3e2b8dae-350e-4ab8-a8ce-016e844b9f0d",
            "type": "tag",
            "attributes": {
              "name": {
                "en": "Long Strip"
              },
              "description": [],
              "group": "format",
              "version": 1
            },
            "relationships": []
          },
          {
            "id": "87cc87cd-a395-47af-b27a-93258283bbc6",
            "type": "tag",
            "attributes": {
              "name": {
                "en": "Adventure"
              },
              "description": [],
              "group": "genre",
              "version": 1
            },
            "relationships": []
          },
          {
            "id": "a1f53773-c69a-4ce5-8cab-fffcd90b1565",
            "type": "tag",
            "attributes": {
              "name": {
                "en": "Magic"
              },
              "description": [],
              "group": "theme",
              "version": 1
            },
            "relationships": []
          },
          {
            "id": "cdc58593-87dd-415e-bbc0-2ec27bf404cc",
            "type": "tag",
            "attributes": {
              "name": {
                "en": "Fantasy"
              },
              "description": [],
              "group": "genre",
              "version": 1
            },
            "relationships": []
          },
          {
            "id": "e197df38-d0e7-43b5-9b09-2842d0c326dd",
            "type": "tag",
            "attributes": {
              "name": {
                "en": "Web Comic"
              },
              "description": [],
              "group": "format",
              "version": 1
            },
            "relationships": []
          },
          {
            "id": "f5ba408b-0e7a-484d-8d49-4e9125ac96de",
            "type": "tag",
            "attributes": {
              "name": {
                "en": "Full Color"
              },
              "description": [],
              "group": "format",
              "version": 1
            },
            "relationships": []
          }
        ],
        "state": "published",
        "chapterNumbersResetOnNewVolume": false,
        "createdAt": "2022-01-10T17:15:53 00:00",
        "updatedAt": "2022-01-10T17:26:26 00:00",
        "version": 4,
        "availableTranslatedLanguages": [
          "ru"
        ]
      },
      "relationships": [
        {
          "id": "5537d8ed-16ed-4f6f-af75-ad7d7edb2ddc",
          "type": "author"
        },
        {
          "id": "36ca9e78-35a9-474d-b4e6-0e4065f0af87",
          "type": "artist"
        },
        {
          "id": "93e21cc1-1f61-46ce-8362-90d9d6888f63",
          "type": "artist"
        },
        {
          "id": "0e703bf4-1996-432c-8620-3c08f2edb37b",
          "type": "cover_art"
        }
      ]
    }
  ],
  "limit": 1,
  "offset": 0,
  "total": 57
}

CodePudding user response:

If your server response is really without the unicode escaped, that is, "犯罪\u8005の子孫た\u3061 ...", then try escaping the data as shown in this example code, to get: "犯罪\\u8005の子孫た\\u3061 ..." (note the \\) and decode it like this:

    URLSession
        .shared
        .dataTask(with: request) { data, response, error in
            if let data = data {
                do {
                    if let sanitisedData = String(data: data, encoding: .utf8)!
                        .replacingOccurrences(of: "\\", with: "\\\\")  // <-- here
                        .data(using: .utf8) {

                        let decoder = JSONDecoder()
                        
                        let decodedResponse = try decoder.decode(Welcome.self, from: sanitisedData)
                        
                        DispatchQueue.main.async {
                            self.data = decodedResponse
                        }
                    }
                } catch let jsonError as NSError {
                    print("JSON Decode Failed: \(jsonError.localizedDescription)")
                }
                
                return
            }
        }.resume()
        

EDIT-1:

you may also need to do this: .replacingOccurrences(of: "\n", with: "\\n")

CodePudding user response:

You don't need to process the data returned at all if the result is simply a text (string to say welcome someone). My solution below is just loading a JSON file returned (as you mentioned above) and then decode the data to Welcome object below

struct Welcome: Codable {
    let ja: String
    
    init(from decoder: Decoder) throws {
        let values = try decoder.container(keyedBy: CodingKeys.self)
        ja = try values.decodeIfPresent(String.self, forKey: .ja) ?? ""
    }
}

func readJsonFile(filename: String) -> String {
    guard let fileUrl = Bundle.main.url(forResource: filename, withExtension: "json") else { fatalError() }
    guard let jsonData = try? String(contentsOf: fileUrl) else {
        return ""
    }
    return jsonData
}


func parseJsonFile() {
    let jsonStr = readJsonFile(filename: "data")
    let jsonData: Data = Data(jsonStr.utf8)
    let decoder = JSONDecoder()
    do {
        let welcome = try decoder.decode(Welcome.self, from: jsonData)
     
        print("\(welcome.ja)")
        
    } catch {
        print(error.localizedDescription)
    }
}

this is the result when I print the welcome.ja's value: 犯罪者の子孫たちが暮らすスラム街。境界線の向こうの人々からは「族民」とさげすまれ、差別を受けていた。孤児だった少年・ルドは、育ての親であるレグトと共にスラム街に住み、常人離れした身体能力を武器に生計を立てていた。だがある日、身に覚えのない罪を着せられ、スラムの人々でさえ恐れる「奈落」へと落とされてしまう……。

  • Related