解码有时可能会改变的数据

时间:2019-10-12 23:53:58

标签: swift swift4 codable decodable

我有一个名为Info的结构,该结构根据接收到的数据进行解码。但是有时,数据中的值之一可以是double或double数组。我该如何设置我的结构?

这是我的结构:

struct Info: Decodable {

    let author: String
    let title: String
    let tags: [Tags]
    let price: [Double]

    enum Tags: String, Decodable {
        case nonfiction
        case biography
        case fiction
    }

}

根据网址,我要么获得双倍价格

{
    "author" : "Mark A",
    "title" : "The Great Deman",
    "tags" : [
      "nonfiction",
      "biography"
    ],
    "price" : "242"

}

或者我将其作为双打数组

{
    "author" : "Mark A",
    "title" : "The Great Deman",
    "tags" : [
      "nonfiction",
      "biography"
    ],
    "price" : [
    "242",
    "299",
    "335"
    ]

}

我想设置结构,以便如果我收到一个double而不是一个double数组,则应该将price解码为1个double的数组。

我们将不胜感激。

谢谢

1 个答案:

答案 0 :(得分:5)

您的JSON实际上是一个字符串或一个字符串数组。因此,您需要创建一个自定义解码器进行解码,然后将其转换为Double:

extension Info: Codable {
    public init(from decoder: Decoder) throws {
        let container = try decoder.container(keyedBy: CodingKeys.self)
        author = try container.decode(String.self, forKey: .author)
        title  = try container.decode(String.self, forKey: .title)
        tags = try container.decode([Tags].self, forKey: .tags)
        do {
            price = try [Double(container.decode(String.self, forKey: .price)) ?? .zero]
        } catch {
            price = try container.decode([String].self, forKey: .price).compactMap(Double.init)
        }
    }
}

let infoData = Data("""
{
    "author" : "Mark A",
    "title" : "The Great Deman",
    "tags" : [
      "nonfiction",
      "biography"
    ],
    "price" : "242"

}
""".utf8)
do {
    let info = try JSONDecoder().decode(Info.self, from: infoData)
    print("price",info.price)  // "price [242.0]\n"
} catch {
    print(error)
}

游乐场测试

let infoData2 = Data("""
{
    "author" : "Mark A",
    "title" : "The Great Deman",
    "tags" : [
      "nonfiction",
      "biography"
    ],
    "price" : [
    "242",
    "299",
    "335"
    ]

}
""".utf8)

do {
    let info = try JSONDecoder().decode(Info.self, from: infoData2)
    print("price",info.price)  // "price [242.0, 299.0, 335.0]\n"
} catch {
    print(error)
}

<!DOCTYPE html>
<head>
<title>Feedback Form</title>
<style>
h1 { color: red; padding: 10px; text-decoration: underline; }
.defaultTextBox {
padding: 0;
height: 20px;
position: relative;
left: 0;
outline: none;
border: 1px solid #cdcdcd;
border-color: rgba(0,0,0,.15);
background-color: white;
font-size: 16px;
.defaultTextArea {
padding: 0;
height: 100px;
position: relative;
left: 0;
outline: none;
border: 1px solid #cdcdcd;
border-color: rgba(0,0,0,.15);
background-color: white;
font-size: 16px;
.button {
background-color: #4CAF50; /* Green */
border: none;
color: white;
padding: 15px 32px;
text-align: center;
text-decoration: none;
display: inline-block;
font-size: 16px;
}
}
</style>
</head>
<body>
<script>

function formsubmission(){
alert("Thank you for submitting feedback");
if(ValidateEmail()){
if(textAreaValidation()){
if(phoneNumberValidation()){
return true;
}else{
return false;
}
}else{
return false;
}
}
}
function ValidateEmail()   
{
if (/^\w+([\.-]?\w+)*@\w+([\.-]?\w+)*(\.\w{2,3})+$/.test(registraionForm.emailTxt.value))
{
return (true)
}
alert("You have entered an invalid email address!")
return (false)
}
function textAreaValidation()
{
var comments = registraionForm.comments.value;
if(comments.length == 0)
    {
    return (false);
    }
    else
    {
    return (true);
    }
}

function phoneNumberValidation()
{
    var p1 = phone.search(/^\d{3}[-\s]{0,1}\d{3}[-\s]{0,1}\d{4}$/);
    var p2 = phone.search(/^\d{3}[-\s]{0,1}\d{4}$/);
    if(p1 == 0 || p2 == 0)
    {
    return true;
    }
    else 
    {
    return false;
    }

}
</script
<h1 >Please Provide The Daily Grind Your Feedback</h1>

<tr><td><form name="FeedbackForm" method="post" action="processcontact.php">
<Table>

<TD>
<Table border="0">
<TR>
<TD><label>First Name</label></TD>
<TD><input type="text" name="FirstNameTxt" required class="defaultTextBox" /></TD>
</TR>
<TR>
<TD><label>Last Name</label></TD>
<TD><input type="text" name="LastNameTxt" required class="defaultTextBox" /></TD>
</TR>
<TR>
<TD><label>Phone Number</label></TD>
<TD><input type="text" name="PhoneTxt" required class="defaultTextBox" /></TD>
</TR>
<TR>
<TD><label>Email</label></TD>
<TD><input type="text" name="emailTxt" required class="defaultTextBox" /></TD>
</TR>
<TR>
<TD><label>Subject</label></TD>
<TD><input type="text" name="SubjectTxt" required class="defaultTextBox" /></TD>
</TR>
<TR>

    <td colspan="2">Please check here if you wish to receive a reply:
    <input type="checkbox" name="reply" value= "yes" /></td>
</TD>
</TR>
<TR>
<TD>Comments</TD>
<TD>
<textarea name="comments" rows="4" cols="50" class="defaultTextArea" >Write your feedback here</textarea>
</TD>
</TR>
<TR>
<TD>&nbsp;</TD>
<TD><input type="submit" name="formSubmit" value="Submit" onclick="formSubmit();"/></TD>
</TR>
</Table>
</TD>
</TR>
</Table>
</form>
</body>
</html>