Re: [web-nfc] What's the value of `toJSON()`? (#366)

The more I think about it, the more I'd like us to get rid of JSON, and even other special casing. I feel like Web NFC is trying to be both an API and a library at the same time. So here's my proposal.

I believe great documentation will make this API shine.

## Proposed spec changes

1. Merge "json" and "opaque" recordType into new "media" recordType
2. IDL changes (see below)

```diff
  [Exposed=Window]
  interface NDEFRecord {
    constructor(NDEFRecordInit recordInit);

    readonly attribute NDEFRecordType recordType;
    readonly attribute USVString mediaType;
    readonly attribute USVString id;
+   readonly attribute DataView? data;

-   USVString? text();
-   [NewObject] ArrayBuffer? arrayBuffer();
-   [NewObject] any json();
    sequence<NDEFRecord> toRecords();
  };

  dictionary NDEFRecordInit {
    NDEFRecordType recordType;
    USVString mediaType;
    USVString id;

    any data;
  };
```


## Why

- new "data" attribute is a DataView: it is already used in other Web Devices API such as [Web Bluetooth](https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattcharacteristic-value), [Web USB](https://wicg.github.io/webusb/#dom-usbisochronousintransferresult-data), [Web HID](https://wicg.github.io/webhid/#dom-hidinputreportevent-data) and is great for handling bytes.
- Using web platform primitives like `TextDecoder` for decoding text tags is really easy and can be reused. Moreover, it allows web developers to specify the encoding (UTF-16 for instance) which, once again, gives back web developer control. This allows us to not try to make the API [smart](https://w3c.github.io/web-nfc/#text-record) about it.  
- "mediaType" is required only for "media" recordType instead of requiring "application/json" for "json". Note that documentation will basically say JSON has to be in a media record type: "Text is user facing, don't use it for JSON.

## JS example

```js
async function writeToNfcTag() {
  const writer = new NFCWriter();
  const records = [
    {
      recordType: "text",
      data: "hello"
    },
    {
      recordType: "url",
      data: "https://google.com"
    },
    {
      recordType: "media",
      mediaType: "application/json",
      data: { key1: "value1", key2: "value2" }
    },
    {
      recordType: "media",
      mediaType: "image/png",
      data: await (await fetch("image.png")).arrayBuffer()
    },
    {
      recordType: "android.com:pkg", // Known external type
      data: new TextEncoder().encode("org.chromium.webapk.ace0b15a6ce931426")
        .buffer
    },
    {
      recordType: "example.com:a", // Custom external type
      data: Uint8Array.of(1)
    }
  ];

  return writer.push({ records });
}

function readNfcTag() {
  const reader = new NFCReader();
  reader.scan();
  reader.onreading = ({ message }) => {
    const decoder = new TextDecoder(); // UTF-8 by default

    for (const record of message.records) {
      const data = record.data; // NEW!
      switch (record.recordType) {
        case "text":
          console.log(`Text: ${decoder.decode(data)}`);
          break;

        case "url":
          console.log(`URL: ${decoder.decode(data)}`);
          break;

        case "media":
          // Let developer handle media case
          if (record.mediaType === "application/json") {
            console.log(`JSON: ${JSON.parse(decoder.decode(data))}`);

          } else if (record.mediaType.startsWith("image/")) {
            const blob = new Blob(data, { type: record.mediaType });
            const img = document.createElement("img");
            img.src = URL.createObjectURL(blob);
            document.body.appendChild(img);

          } else {
            console.log(`Media not handled`);
          }
          break;

        case "android.com:pkg":
          console.log(`AAR Package Name: ${decoder.decode(data)}`);
          break;

        case "example.com:a":
          console.log(`My custom external type: ${data.getUint8(0)}`);
          break;
      }
    }
  };
}
```

-- 
GitHub Notification of comment by beaufortfrancois
Please view or discuss this issue at https://github.com/w3c/web-nfc/issues/366#issuecomment-542104572 using your GitHub account

Received on Tuesday, 15 October 2019 08:39:30 UTC