这是我正在使用的代码,
//Your path here.
String path = Environment.getExternalStorageDirectory().getAbsolutePath() + "/example.pdf";
File file = new File(path);
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(Uri.fromFile(file), "application/pdf");
intent.setFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
startActivity(intent);
此处,File file = new File(uri.getPath());
由struct CreatePostResponseModel : Codable{
var transcodeId:String?
var id:String = ""
enum TopLevelCodingKeys: String, CodingKey {
case _transcode = "_transcode"
case _transcoder = "_transcoder"
}
enum CodingKeys:String, CodingKey{
case id = "_id"
}
init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: TopLevelCodingKeys.self)
if let transcodeId = try container.decodeIfPresent(String.self, forKey: ._transcode) {
self.transcodeId = transcodeId
}else if let transcodeId = try container.decodeIfPresent(String.self, forKey: ._transcoder) {
self.transcodeId = transcodeId
}
}
}
或transcodeId
决定。
但是我希望_transcode
和其余的键(此处未包括)被自动解码。我该怎么办?
答案 0 :(得分:1)
一旦以init(from:)
类型实现Codable
,就需要手动解析所有键。
struct CreatePostResponseModel: Decodable {
var transcodeId: String?
var id: String
enum CodingKeys:String, CodingKey{
case id, transcode, transcoder
}
init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
id = try container.decodeIfPresent(String.self, forKey: .id) ?? ""
if let transcodeId = try container.decodeIfPresent(String.self, forKey: .transcode) {
self.transcodeId = transcodeId
} else if let transcodeId = try container.decodeIfPresent(String.self, forKey: .transcoder) {
self.transcodeId = transcodeId
}
}
}
在上面的代码中,
Codable
。使用Decodable
就足够了。enums
使用多个CodingKey
似乎是不必要的。您可以使用一个enum CodingKeys
。rawValue
的{{1}}在case
中。因此,enum CodingKeys
中没有"_transcode"
和"_transcoder"
rawValues
的要求。除此之外,您还可以将TopLevelCodingKeys
用作keyDecodingStrategy
来处理下划线表示法( 蛇格表示法 ),即
.convertFromSnakeCase
因此,您无需显式处理所有蛇形键。 do {
let decoder = JSONDecoder()
decoder.keyDecodingStrategy = .convertFromSnakeCase //here.....
let model = try decoder.decode(CreatePostResponseModel.self, from: data)
print(model)
} catch {
print(error)
}
将自行处理。
答案 1 :(得分:1)
这可能是适合您的好解决方案之一,无论您想在哪里为一个变量添加多个键:
var transcodeId:String?
public init(from decoder: Decoder) throws {
do {
let container = try decoder.container(keyedBy: CodingKeys.self)
transcodeId = container.getValueFromAvailableKey(codingKeys: [CodingKeys._transcoder,CodingKeys._transcode])
} catch {
print("Error reading config file: \(error.localizedDescription)")
}
}
extension KeyedDecodingContainerProtocol{
func getValueFromAvailableKey(codingKeys:[CodingKey])-> String?{
for key in codingKeys{
for keyPath in self.allKeys{
if key.stringValue == keyPath.stringValue{
do{
return try self.decodeIfPresent(String.self, forKey: keyPath)
} catch {
return nil
}
}
}
}
return nil
}
}
希望有帮助。
答案 2 :(得分:0)
由编译器生成的init(from:)
是全有还是全无。您不能让它解码某些密钥,而不能“手动”解码其他密钥。
使用编译器生成的init(from:)
的一种方法是给struct
两者都提供可能的编码属性,并使transcodeId
成为计算属性:
struct CreatePostResponseModel: Codable {
var transcodeId: String? {
get { _transcode ?? _transcoder }
set { _transcode = newValue; _transcoder = nil }
}
var _transcode: String? = nil
var _transcoder: String? = nil
var id: String = “”
// other properties
}