a2ui-project / a2ui-project/a2ui

`UpdateDataModel` doesn't distinguish between the value-omitted and value-null cases

Đang mở
#1,896 1 bình luận 0 reaction 1 người được giao Được @andrewkolos nhận Xem trên GitHub
component: genui P2 status: first-line-handled type: bug
Ngôn ngữ chính
TypeScript
Star
16.4k
Fork
1.3k
Merge trung bình
2 ngày 13 giờ
Pull request đã merge (30 ngày)
134

Mô tả

_↴ Ported from [flutter/genui#935](https://github.com/flutter/genui/issues/935) — originally opened by [andrewkolos](https://github.com/andrewkolos) on 2026-05-27._
_Original labels: front-line-handled_

---

The v0.9 spec [distinguishes two intents on `updateDataModel`:](https://github.com/google/A2UI/blob/0e0375749bf8a940d57969d612e74f7221ad246e/specification/v0_9/json/server_to_client.json#L98)

- `"value": ` (key is present): replace the value at `path` with `x`.
- `value` key absent: remove the key at `path`.

`UpdateDataModel.fromJson` collapses both into a single `Object? value` field:

https://github.com/flutter/genui/blob/ae53cc52b35b72312f01b80eeb565163e3c869d7/packages/genui/lib/src/model/a2ui_message.dart#L214-L221

and `toJson()` drops the key with `'value': ?value`. The wire-level distinction is lost as soon as the message hits the model.

https://github.com/flutter/genui/blob/ae53cc52b35b72312f01b80eeb565163e3c869d7/packages/genui/lib/src/model/a2ui_message.dart#L235-L241

Expressed in a code example:

```dart
final message = UpdateDataModel.fromJson({
'surfaceId': 's1',
'path': '/x',
'value': null,
});
final serialized = message.toJson();
expect(serialized.containsKey('value'), isTrue); // fails. value key is dropped.
```

A deeper problem is that the data model also can't distinguish between "set to null" and "remove". There's no method to set a key to `null`. Source:

```dart
final model = InMemoryDataModel();
model.update(DataPath.root, {'x': 1, 'y': 2});
model.update(DataPath('/x'), null);
// Expected per 0.9 spec: {'x': null, 'y': 2}
// Actual: {'y': 2}
```

So even if `UpdateDataModel.fromJson` parsed the distinction correctly, the data model can't set a field to `null`:

https://github.com/flutter/genui/blob/9a748ef7c71689421e1f57bace12a734192351fa/packages/genui/lib/src/model/data_model.dart#L446-L454

I think the most practical impact of this issue would manifest in UIs that use tri-state fields (e.g. `false`, `true`, unset/reset). Not very common, but worth fixing in my opinon. To fix, I suggest splitting the setter API into a setter and a remover, then have `MessageProcessor` branch on `hasValue`.

---

### 1 comment(s) from the original issue

**[andrewkolos](https://github.com/andrewkolos)** commented on 2026-06-24:

Putting this down for now and putting on it my personal backlog. I will reassign myself if I begin looking at it again.

Hướng dẫn đóng góp

Mở hướng dẫn đóng góp

Đánh giá

Issue này chưa được đánh giá.

Nhận issue mới trong hộp thư của bạn

Bản tóm tắt ngắn những issue GitHub phù hợp với người mới.