IOS/Swift/SwiftyJSON: Parse Nested JSON from IBM Watson/Bluemix API

106 views Asked by At

I am receiving some JSON from IBM Watson's tone analyzer API in the format shown below for a piece of text. What I would like to do is capture JSON in an object with a property and value for the main tones, eg. anger:.218 disgust:2.20 etc. for each section of text analyzed. As I analyze more pieces of text I want to add them to an array of these objects.

At this stage, I just want to do something with the api using SwiftyJSON but am confused by the syntax:

The following code, just prints out as nil:

 let anger = JSON(value)["results"][0]["anger"].array?.map { json in
                    json["anger"].stringValue
                                    }
                print (anger)

Would appreciate guidance on how to actually grab the tones and their values.... Thanks in advance for any suggestions.

JSON looks like this:

 {
        "document_tone" =     {
            "tone_categories" =         (
                            {
                    "category_id" = "emotion_tone";
                    "category_name" = "Emotion Tone";
                    tones =                 (
                                            {
                            score = "0.218727";
                            "tone_id" = anger;
                            "tone_name" = Anger;
                        },
                                            {
                            score = "0.210102";
                            "tone_id" = disgust;
                            "tone_name" = Disgust;
                        },
                                            {
                            score = "0.060026";
                            "tone_id" = fear;
                            "tone_name" = Fear;
                        },
                                            {
                            score = "0.076444";
                            "tone_id" = joy;
                            "tone_name" = Joy;
                        },
                                            {
                            score = "0.176849";
                            "tone_id" = sadness;
                            "tone_name" = Sadness;
                        }
                    );
                },
                            {
                    "category_id" = "language_tone";
                    "category_name" = "Language Tone";
                    tones =                 (
                                            {
                            score = 0;
                            "tone_id" = analytical;
                            "tone_name" = Analytical;
                        },
                                            {
                            score = 0;
                            "tone_id" = confident;
                            "tone_name" = Confident;
                        },
                                            {
                            score = 0;
                            "tone_id" = tentative;
                            "tone_name" = Tentative;
                        }
                    );
                },
                            {
                    "category_id" = "social_tone";
                    "category_name" = "Social Tone";
                    tones =                 (
                                            {
                            score = "0.02278";
                            "tone_id" = "openness_big5";
                            "tone_name" = Openness;
                        },
                                            {
                            score = "0.340597";
                            "tone_id" = "conscientiousness_big5";
                            "tone_name" = Conscientiousness;
                        },
                                            {
                            score = "0.541852";
                            "tone_id" = "extraversion_big5";
                            "tone_name" = Extraversion;
                        },
                                            {
                            score = "0.545246";
                            "tone_id" = "agreeableness_big5";
                            "tone_name" = Agreeableness;
                        },
                                            {
                            score = "0.743194";
                            "tone_id" = "emotional_range_big5";
                            "tone_name" = "Emotional Range";
                        }
                    );
                }
            );
        };
    }
1

There are 1 answers

0
thexande On

You can quickly and easily accomplish this with Codable structs in swift 4 and URLSession.

Here is a pure swift solution to your problem. The struct properties map to your json tree, and you might need to change the structs to match the json you're receiving. The json you posted above is in an invalid format otherwise I could have mapped it correctly.

struct Tone: Codable {
    let score: Double
    let tone_id: String
    let tone_name: String
}

struct Category: Codable {
    let category_id: String
    let category_name: String
    let tones: [Tone]
}

struct DocumentTone: Codable {
    let toneCategories: [Category]
}

final class ToneService {
    static func fetchTone(toneUrl: URL, _ completion: @escaping([DocumentTone]) -> Void) {
        URLSession.shared.dataTask(with: toneUrl) { (data, response, error) in
            guard let data = data else { return }
            do {
                let decoder = JSONDecoder()
                // If your json returns a single object, use DocumentTone.self instead of [DocumentTone].self, as well change the completion
                let tone = try decoder.decode([DocumentTone].self, from: data)
                completion(tone)
            } catch let error {
                print(error.localizedDescription)
            }
        }.resume()
    }
}