AnalyticsEvent.fromJson constructor

AnalyticsEvent.fromJson(
  1. Map<String, Object?> json, {
  2. required String source,
})

Decodes an envelope from json.

source is the trusted ingest classification (never read from the payload). For AnalyticsSource.client the decode fails loud (FormatException) when appContext, sessionId, or anonymousId is absent; for AnalyticsSource.server those (and surface) may be absent. tier/source keys in json, if any, are ignored — they are not envelope fields.

Implementation

factory AnalyticsEvent.fromJson(
  Map<String, Object?> json, {
  required String source,
}) {
  _rejectUnsupportedTopLevelFields(json);
  final appContextJson = json['appContext'];
  if (appContextJson != null && appContextJson is! Map) {
    throw FormatException(
      'AnalyticsEvent.appContext must be a map, got: $appContextJson',
    );
  }
  final appContext = appContextJson == null
      ? null
      : AnalyticsAppContext.fromJson(
          (appContextJson as Map).cast<String, Object?>(),
        );
  final anonymousId = _optionalString(json, 'anonymousId');
  final sessionId = _optionalString(json, 'sessionId');

  if (source == AnalyticsSource.client) {
    if (appContext == null) {
      throw const FormatException(
        'AnalyticsEvent: appContext is required for source=client.',
      );
    }
    if (sessionId == null || sessionId.trim().isEmpty) {
      throw const FormatException(
        'AnalyticsEvent: sessionId is required (non-empty) '
        'for source=client.',
      );
    }
    if (anonymousId == null || anonymousId.trim().isEmpty) {
      throw const FormatException(
        'AnalyticsEvent: anonymousId is required (non-empty) '
        'for source=client.',
      );
    }
  }

  final propertiesJson = json['properties'];
  if (propertiesJson != null && propertiesJson is! Map) {
    throw FormatException(
      'AnalyticsEvent.properties must be a map, got: $propertiesJson',
    );
  }
  final properties = (propertiesJson as Map?)?.cast<String, Object?>() ??
      const <String, Object?>{};

  final schemaVersion = json['schemaVersion'];
  if (schemaVersion != null && schemaVersion is! int) {
    throw FormatException(
      'AnalyticsEvent.schemaVersion must be an int, got: $schemaVersion',
    );
  }

  return AnalyticsEvent(
    eventId: _requireNonEmptyString(json, 'eventId'),
    name: _requireNonEmptyString(json, 'name'),
    occurredAt: _requireUtc(json, 'occurredAt'),
    schemaVersion: (schemaVersion as int?) ?? 1,
    surface: _optionalString(json, 'surface'),
    surfaceId: _optionalString(json, 'surfaceId'),
    surfaceVersion: _optionalString(json, 'surfaceVersion'),
    placementId: _optionalString(json, 'placementId'),
    anonymousId: anonymousId,
    sessionId: sessionId,
    surfaceSessionId: _optionalString(json, 'surfaceSessionId'),
    userId: _optionalString(json, 'userId'),
    appContext: appContext,
    productId: _optionalString(json, 'productId'),
    offerId: _optionalString(json, 'offerId'),
    properties: properties,
  );
}