Skip to content

Instantly share code, notes, and snippets.

@danielgarbien
Last active November 12, 2021 17:56
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save danielgarbien/3c3ee4112e7dcd68b980830dd26b3ccb to your computer and use it in GitHub Desktop.
Save danielgarbien/3c3ee4112e7dcd68b980830dd26b3ccb to your computer and use it in GitHub Desktop.
NDJSON parser
import Foundation
import XCTest
class NDJSONParserTests: XCTestCase {
let ndJson = "{ \"key\": \"value\" }\n"
func testSimpleNDJSON() {
let twoLines = ndJson + ndJson
XCTAssert(parseDataFromString(twoLines).count == 2)
}
func testEmptyNDJSON() {
XCTAssert(parseDataFromString("").count == 0)
}
func testDoubleNewLineNDJSON() {
let doubleNewLines = ndJson + "\n" + ndJson
XCTAssert(parseDataFromString(doubleNewLines).count == 2)
}
func testOneNewLineNDJSON() {
let doubleNewLines = "\n"
XCTAssert(parseDataFromString(doubleNewLines).count == 0)
}
func testLeadingNewLineNDJSON() {
let leadingNewLine = "\n" + ndJson
XCTAssert(parseDataFromString(leadingNewLine).count == 1)
}
func testNoEndingNewLine() {
let noEndingNewLine = "{ \"key\": \"value\" }"
XCTAssert(parseDataFromString(noEndingNewLine).count == 1)
}
func testPerformance() {
let huge = Array(count: 100000, repeatedValue: ndJson).reduce("", combine: +)
self.measureBlock {
self.parseDataFromString(huge)
}
}
private func parseDataFromString(string: String) -> [AnyObject] {
let data = string.dataUsingEncoding(NSUTF8StringEncoding)!
do {
return try NDJSONParser.JSONObjectsWithData(data, options: [])
} catch {
XCTFail(String(error))
return []
}
}
}
import Foundation
class NDJSONParser {
/**
Simple NDJSON parser implementation.
String from NDJSON data is converted to JSON array of elements formed with lines. This array is then to be deserialized with Foundation's NSJSONSerialization class.
Empty lines are disregarded.
- parameter data: A data object containing UTF8 encoded text with NDJSON.
- parameter opt: Options for reading the JSON passed to NSJSONSerialization.
- throws: Errors thrown by NSJSONSerialization.
- returns: Array of JSON objects
*/
class func JSONObjectsWithData(data: NSData, options opt: NSJSONReadingOptions = []) throws -> [AnyObject] {
let nonEmptyLines = String(data: data, encoding: NSUTF8StringEncoding)!
.componentsSeparatedByString("\n").filter{ !$0.isEmpty }
let string =
"[" + nonEmptyLines.joinWithSeparator(",")
+ "]"
let data = string.dataUsingEncoding(NSUTF8StringEncoding)!
return try NSJSONSerialization.JSONObjectWithData(data, options: opt) as! [AnyObject]
}
}
@cslosiu
Copy link

cslosiu commented Nov 12, 2021

latest swift syntax for the class func:

 class func JSONObjectsWithData(data: Data, options opt: JSONSerialization.ReadingOptions = []) throws -> [AnyObject] {
    let nonEmptyLines = String(data: data, encoding: String.Encoding.utf8)!
          .components(separatedBy: "\n").filter{ !$0.isEmpty }
    let string =   "[" + nonEmptyLines.joined(separator: ",")  + "]"
    let data = string.data(using: String.Encoding.utf8)!
    return try JSONSerialization.jsonObject(with: data, options: opt) as! [AnyObject]
  }

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment