0

I need to create an answer JSON with nested objects

I tried to use mappable but it won't solve the problem

I need to create this kind of array

{  
   "interactionId":"daade6b6adcd8b063a355e28bc1f1341",
   "futureSurveyAnswers":[  
      {  
         "type":"imagepicker",
         "qcode":"vxo20zeezo",
         "values":[  
            {  
               "value":"lion"
            }
         ]
      },
      {  
         "type":"radiogroup",
         "qcode":"s4ep4s0shf",
         "values":[  
            {  
               "value":"item1"
            }
         ]
      },
      {  
         "type":"checkbox",
         "qcode":"76k5cpnpki",
         "values":[  
            {  
               "value":"item1"
            },
            {  
               "value":"item2"
            }
         ]
      }
   ],
   "originalResultArray":"{\"question2\":\"item1\",\"question3\":[\"item1\",\"item2\"],\"question1\":\"lion\"}"
}
1
  • Show what you tried yet. Commented Jul 9, 2019 at 6:42

1 Answer 1

2

Currently probably the best solution to use is Codable protocol. There are many examples and tutorials online so please do check one or two, I am sure you will find it very simple to use.

The point is that you can encode concrete classes or structures directly to (and from) JSON. So your problem is then not in JSON itself but just structuring your classes. For instance:

class Survey {

    class Answer {
        enum AnswerType: String {
            case imagepicker
        }
        class Value {
            var value: String?
        }

        var type: AnswerType = .imagepicker
        var qcode: String?
        var values: [Value] = [Value]()
    }

    let interactionId: String
    var futureSurveyAnswers: [Answer] = [Answer]()
    var originalResultArray: String?

    init(interactionId: String) { self.interactionId = interactionId }
}

This way you can easily modify your structure as you want to. For instance:

let survey = Survey(interactionId: "0")
survey.futureSurveyAnswers.append({
    let answer = Survey.Answer()
    answer.qcode = "test"
    return answer
}())

So to extend it to codable all you need to do is actually append Codable protocol to your class and any embedded component:

class Survey: Codable {

    class Answer: Codable {
        enum AnswerType: String, Codable {
            case imagepicker
        }
        class Value: Codable {
            var value: String?
        }

        var type: AnswerType = .imagepicker
        var qcode: String?
        var values: [Value] = [Value]()
    }

    let interactionId: String
    var futureSurveyAnswers: [Answer] = [Answer]()
    var originalResultArray: String?

    init(interactionId: String) { self.interactionId = interactionId }
}

Now you can get JSON as simple as the following:

let survey = Survey(interactionId: "0")
survey.futureSurveyAnswers.append({
    let answer = Survey.Answer()
    answer.values.append({
        let value = Survey.Answer.Value()
        value.value = "some"
        return value
    }())
    answer.qcode = "test"
    return answer
}())

let encoder = JSONEncoder()
if let jsonData = try? encoder.encode(survey) {
    print("Generated data: \(jsonData)")
}

I hope this puts you in the right direction.

From comments this is what I used as a test example for JSON:

class Survey: Codable {

    class Answer: Codable {
        enum AnswerType: String, Codable {
            case imagepicker
        }
        class Value: Codable {
            var value: String?
            init(value: String? = nil) { self.value = value }
        }

        var type: AnswerType = .imagepicker
        var qcode: String?
        var values: [Value] = [Value]()
    }

    let interactionId: String
    var futureSurveyAnswers: [Answer] = [Answer]()
    var originalResultArray: String?

    init(interactionId: String) { self.interactionId = interactionId }
}

func addTestAnswer(to survey: Survey) {
    let answer = Survey.Answer()
    answer.values.append(.init(value: "Random value \(Int.random(in: 1...100))"))
    answer.values.append(.init(value: "Random value \(Int.random(in: 1...100))"))
    answer.values.append(.init(value: "Random value \(Int.random(in: 1...100))"))
    answer.values.append(.init(value: "Random value \(Int.random(in: 1...100))"))
    survey.futureSurveyAnswers.append(answer)
}

func testRandomSurveyJSON() {
    let survey = Survey(interactionId: "randomSurvey")
    addTestAnswer(to: survey)
    addTestAnswer(to: survey)
    addTestAnswer(to: survey)
    addTestAnswer(to: survey)
    addTestAnswer(to: survey)

    print("Got JSON: \(String(data: try! JSONEncoder().encode(survey), encoding: .utf8)!)")
}

And got the following result:

Got JSON: {"interactionId":"randomSurvey","futureSurveyAnswers":[{"type":"imagepicker","values":[{"value":"Random value 74"},{"value":"Random value 4"},{"value":"Random value 26"},{"value":"Random value 93"}]},{"type":"imagepicker","values":[{"value":"Random value 43"},{"value":"Random value 65"},{"value":"Random value 38"},{"value":"Random value 88"}]},{"type":"imagepicker","values":[{"value":"Random value 56"},{"value":"Random value 88"},{"value":"Random value 57"},{"value":"Random value 94"}]},{"type":"imagepicker","values":[{"value":"Random value 66"},{"value":"Random value 52"},{"value":"Random value 89"},{"value":"Random value 27"}]},{"type":"imagepicker","values":[{"value":"Random value 53"},{"value":"Random value 93"},{"value":"Random value 30"},{"value":"Random value 55"}]}]}

which seems to be correct.

Sign up to request clarification or add additional context in comments.

10 Comments

how to add data to the values section
@VSoftwareSolutions Do you mean like: answer.values.append({ let value = Survey.Answer.Value() value.value = "some" return value }())
how can i print out the whole data set once i write all data
@VSoftwareSolutions Not sure what you mean; the JSON? JSON is binary data but is partially human readable when converted to UTF8 string. To do so all you need to do is initialize a String with JSON data using UTF8 string encoding: print("\(String(data: jsonData, encoding: .utf8)!)")
im writing data one at a time to this object so once its compleate, is there a way to print the whole json object
|

Your Answer

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.