2017-11-02 36 views
11

Tôi đang cố gắng để serialize đối tượng của tôi như sau:Swift Chuỗi thoát khi tuần tự để JSON sử dụng Codable

import Foundation 

struct User: Codable { 
    let username: String 
    let profileURL: String 
} 

let user = User(username: "John", profileURL: "http://google.com") 

let json = try? JSONEncoder().encode(user) 

if let data = json, let str = String(data: data, encoding: .utf8) { 
    print(str) 
} 

Tuy nhiên trên hệ điều hành MacOS tôi nhận được như sau:

{"profileURL":"http:\/\/google.com","username":"John"} 

(lưu ý thoát '/' tính cách).

Trong khi trên máy Linux Tôi nhận:

{"username":"John","profileURL":"http://google.com"} 

Làm thế nào tôi có thể làm cho JSONEncoder gửi lại mẫu unescaped trên hệ điều hành MacOS?

Tôi cần chuỗi trong JSON phải được loại bỏ hoàn toàn.

+2

Đừng lo lắng về điều đó. Không có gì sai với chuỗi của bạn –

+3

Đây không phải là một tùy chọn, vì tôi phải ký dữ liệu và xác nhận chữ ký. Có thêm ký tự biểu thị chữ ký không hợp lệ – tofiffe

+0

JSON được xác thực trên phía máy chủ, mà tôi không thể sửa đổi. – tofiffe

Trả lời

2

tôi đã kết thúc bằng replacingOccurrences(of:with:), có thể không phải là giải pháp tốt nhất, nhưng nó giải quyết vấn đề này:

import Foundation 

struct User: Codable { 
    let username: String 
    let profileURL: String 
} 

let user = User(username: "John", profileURL: "http://google.com") 

let json = try? JSONEncoder().encode(user) 

if let data = json, let str = String(data: data, encoding: .utf8)?.replacingOccurrences(of: "\\/", with: "/") { 
    print(str) 
    dump(str) 
} 
-2

Thực ra bạn không thể làm điều đó vì trong MacOS và Linux là một hệ thống thoát khác nhau. Trên Linux // được cho phép, macOS - not (nó sử dụng NSSerialization). Vì vậy, bạn chỉ có thể thêm phần trăm mã hóa trên chuỗi của bạn, đảm bảo cho bạn chuỗi bằng nhau trên macOS và linux, chuỗi phải đăng lên máy chủ và xác thực đúng. Khi thêm phần trăm thoát, đặt CharacterSet.urlHostAllowed. Có thể được thực hiện như thế này:

init(name: String, profile: String){ 
     username = name 
     if let percentedString = profile.addingPercentEncoding(withAllowedCharacters: CharacterSet.urlHostAllowed){ 
      profileURL = percentedString 
     }else{ 
      profileURL = "" 
     } 
    } 

Trong cùng một cách thức, bạn có thể removePercentEncoding và bạn không cần CHỈNH MÁY CHỦ PHỤ !!!

+1

Như nó đã được đề cập, json được ký, thêm phần trăm mã hóa thay đổi chữ ký và băm – tofiffe

+0

@ tofiffe bạn không thể gửi url như tham số như nó được. Hoặc thêm removepercent trên phía máy chủ (mà bạn không thể) hoặc gửi profileUrl với các ký hiệu thoát. Ngay cả trên Linux, nếu bạn tạo một chuỗi như vậy, không có sự bảo đảm nào bạn có thể gửi đến máy chủ như nó. Nếu bạn gửi nó đến máy chủ với các biểu tượng thoát, nó sẽ thay đổi băm của url hồ sơ, phải không? Vì vậy, những gì, mỗi lần gửi chuỗi phần trăm để xác nhận nó hoặc một cái gì đó. –

1

Tôi hiểu rồi. Vấn đề là nó không chứa bất kỳ ký tự nào. Nó chỉ là tài sản của nhanh chóng mà nó sẽ luôn luôn trở lại như một chuỗi trên một giao diện điều khiển. Cách giải quyết là phân tích cú pháp j-son.

Tuy nhiên, bạn có thể được sử dụng dưới đây giải pháp thay thế '\ /' với "/" chuỗi

let newString = str.replacingOccurrences(of: "\\/", with: "/") 
print(newString) 
+0

Như tôi đã thể hiện trong câu hỏi, nó không phải lúc nào cũng trả về một chuỗi thoát (nó hoạt động tốt trên các máy Linux). Khi JSON được phân tích cú pháp vấn đề đã biến mất, nhưng tôi cần JSON giống như trên máy chủ – tofiffe

0

Trong khi chơi xung quanh JSONEncoder/JSONDecoder, tôi thấy rằng các loại URL là tổn hao trên mã hóa -> giải mã.

Khởi tạo bằng chuỗi, liên quan đến một URL khác.

init?(string: String, relativeTo: URL?) 

Có thể giúp tài liệu táo này: https://developer.apple.com/documentation/foundation/url

sử dụng phiên bản PropertyList, tuy nhiên:

let url = URL(string: "../", relativeTo: URL(string: "http://google.com"))! 
let url2 = PropertyListDecoder().decode([URL].self, from: PropertyListEncoder().encode([User])) 

cách khác

let url = URL(string: "../", relativeTo: URL(string: "http://google.com"))! 
let url2 = JSONDecoder().decode([URL].self, from: JSONEncoder().encode([User])) 

Hope sẽ hữu ích cho bạn !!

Các vấn đề liên quan