/// <summary> /// Deserialize a Threat Model and adds it to the list of known Threat Models. /// </summary> /// <param name="json">Serialized Json of the Threat Model, as byte array.</param> /// <param name="ignoreMissingMembers">Optional flag to specify to ignore information that is unknown.</param> /// <param name="newThreatModelId">Optional identifier to be used for the Threat Model replacing its configured one.</param> /// <returns>The deserialized Threat Model.</returns> public static IThreatModel Deserialize([NotNull] byte[] json, bool ignoreMissingMembers = false, Guid?newThreatModelId = null)//, bool addToKnownInstances = true) { IThreatModel result = null; if (json.Length > 0) { string jsonText = null; if (json[0] == 0xFF) { jsonText = Encoding.Unicode.GetString(json, 2, json.Length - 2); } else { jsonText = Encoding.Unicode.GetString(json); } if (newThreatModelId.HasValue && newThreatModelId != Guid.Empty) { var parsed = JObject.Parse(jsonText); var id = parsed.GetValue("id")?.ToObject <string>(); if (!string.IsNullOrWhiteSpace(id)) { jsonText = jsonText.Replace(id, newThreatModelId?.ToString("D")); } } var binder = new KnownTypesBinder(); using (var textReader = new StringReader(jsonText)) using (var reader = new JsonTextReader(textReader)) { var serializer = new JsonSerializer { TypeNameHandling = TypeNameHandling.All, SerializationBinder = binder, MaxDepth = 128, MissingMemberHandling = ignoreMissingMembers ? MissingMemberHandling.Ignore : MissingMemberHandling.Error }; result = serializer.Deserialize <IThreatModel>(reader); } if (result != null) { try { if (!binder.HasUnknownTypes) { result.ResetDirty(); } result.SuspendDirty(); if (_instances.Any(x => x.Id == result.Id)) { throw new ExistingModelException(result); } else { result.Cleanup(); result.PropertySchemasNormalization(); _instances.Add(result); var method = result.GetType() .GetMethod("RegisterEvents", BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.InvokeMethod, null, new Type[] { }, null); if (method != null) { method.Invoke(result, null); } var processors = ExtensionUtils.GetExtensions <IPostLoadProcessor>()?.ToArray(); if (processors?.Any() ?? false) { foreach (var processor in processors) { processor.Process(result); } } } } finally { result.ResumeDirty(); } } } return(result); }