static LogEvent ReadFromJObject(int lineNumber, JObject jObject) { var timestamp = GetRequiredTimestampField(lineNumber, jObject, ClefFields.Timestamp); string messageTemplate; if (TryGetOptionalField(lineNumber, jObject, ClefFields.MessageTemplate, out var mt)) { messageTemplate = mt; } else if (TryGetOptionalField(lineNumber, jObject, ClefFields.Message, out var m)) { messageTemplate = MessageTemplateSyntax.Escape(m); } else { messageTemplate = null; } var level = LogEventLevel.Information; if (TryGetOptionalField(lineNumber, jObject, ClefFields.Level, out string l)) { level = (LogEventLevel)Enum.Parse(typeof(LogEventLevel), l); } Exception exception = null; if (TryGetOptionalField(lineNumber, jObject, ClefFields.Exception, out string ex)) { exception = new TextException(ex); } var parsedTemplate = messageTemplate == null ? new MessageTemplate(Enumerable.Empty <MessageTemplateToken>()) : Parser.Parse(messageTemplate); var renderings = NoRenderings; if (jObject.TryGetValue(ClefFields.Renderings, out JToken r)) { var renderedByIndex = r as JArray; if (renderedByIndex == null) { throw new InvalidDataException($"The `{ClefFields.Renderings}` value on line {lineNumber} is not an array as expected."); } renderings = parsedTemplate.Tokens .OfType <PropertyToken>() .Where(t => t.Format != null) .Zip(renderedByIndex, (t, rd) => new Rendering(t.PropertyName, t.Format, rd.Value <string>())) .ToArray(); } var properties = jObject .Properties() .Where(f => !ClefFields.All.Contains(f.Name)) .Select(f => { var name = ClefFields.Unescape(f.Name); var renderingsByFormat = renderings.Length != 0 ? renderings.Where(rd => rd.Name == name).ToArray() : NoRenderings; return(PropertyFactory.CreateProperty(name, f.Value, renderingsByFormat)); }) .ToList(); // TODO: this should attempt to support numeric ids. if (TryGetOptionalField(lineNumber, jObject, ClefFields.EventId, out var eventId)) { properties.Add(new LogEventProperty("@i", new ScalarValue(eventId))); } return(new LogEvent(timestamp, level, exception, parsedTemplate, properties)); }