static void AppendCommentList(StringBuilder sb, List <V1CommentModel> rootComments, JsonSerializerOptions options) { var stack = new Stack <(List <V1CommentModel> List, int NextIndex)>(); stack.Push((rootComments, 0)); while (stack.Any()) { var(list, index) = stack.Pop(); if (index == 0) { sb.Append("["); } if (index == list.Count) { sb.Append("]}"); continue; } stack.Push((list, index + 1)); var comment = list[index]; if (index == 0) { sb.Append("{"); } else { sb.Append(",{"); } AppendProperty(sb, "id", comment.Id, options); AppendProperty(sb, "body", comment.Body, options); AppendProperty(sb, "date", V1DateTimeOffsetConverter.ToJsonString(comment.Date), options); AppendProperty(sb, "category", V1ModerationFlagConverter.ToJsonString(comment.Category), options); AppendProperty(sb, "author", comment.Author, options); AppendProperty(sb, "preview", comment.Preview, options); sb.Append("\"comments\":"); stack.Push((comment.Comments, 0)); } }
public async Task <ContentResult> Thread(int threadId) { var chattyThread = await _chattyProvider.GetThread(threadId); var list = new List <V1RootCommentModel>(); var maxDepth = chattyThread.Posts.Max(x => x.Depth); var lastCommentAtDepth = new V1CommentModel[maxDepth + 1]; var op = chattyThread.Posts[0]; var v1RootCommentModel = new V1RootCommentModel { Comments = new List <V1CommentModel>(), ReplyCount = chattyThread.Posts.Count, Body = op.Body, Date = op.Date, Participants = GetParticipants(chattyThread), Category = op.Category, LastReplyId = $"{chattyThread.Posts.Max(x => x.Id)}", Author = op.Author, Preview = ThreadParser.PreviewFromBody(op.Body), Id = $"{op.Id}" }; foreach (var post in chattyThread.Posts.Skip(1)) { var v1CommentModel = new V1CommentModel { Comments = new List <V1CommentModel>(), Body = post.Body, Date = post.Date, Category = post.Category, Author = post.Author, Preview = ThreadParser.PreviewFromBody(post.Body), Id = $"{post.Id}" }; if (post.Depth == 1) { v1RootCommentModel.Comments.Add(v1CommentModel); } else { lastCommentAtDepth[post.Depth - 1].Comments.Add(v1CommentModel); } lastCommentAtDepth[post.Depth] = v1CommentModel; } var response = new V1ThreadModel { Comments = new List <V1RootCommentModel> { v1RootCommentModel } }; // the serializer has a maximum depth that is too low, even if you reconfigure it to the hard max. var sb = new StringBuilder(); var options = new JsonSerializerOptions { PropertyNamingPolicy = JsonNamingPolicy.CamelCase }; sb.Append("{"); AppendProperty(sb, "id", v1RootCommentModel.Id, options); AppendProperty(sb, "reply_count", v1RootCommentModel.ReplyCount, options); AppendProperty(sb, "body", v1RootCommentModel.Body, options); AppendProperty(sb, "date", V1DateTimeOffsetConverter.ToJsonString(v1RootCommentModel.Date), options); AppendProperty(sb, "participants", v1RootCommentModel.Participants, options); AppendProperty(sb, "category", V1ModerationFlagConverter.ToJsonString(v1RootCommentModel.Category), options); AppendProperty(sb, "last_reply_id", v1RootCommentModel.LastReplyId, options); AppendProperty(sb, "author", v1RootCommentModel.Author, options); AppendProperty(sb, "preview", v1RootCommentModel.Preview, options); sb.Append("\"comments\":[{"); AppendProperty(sb, "id", v1RootCommentModel.Id, options); AppendProperty(sb, "body", v1RootCommentModel.Body, options); AppendProperty(sb, "date", V1DateTimeOffsetConverter.ToJsonString(v1RootCommentModel.Date), options); AppendProperty(sb, "category", V1ModerationFlagConverter.ToJsonString(v1RootCommentModel.Category), options); AppendProperty(sb, "author", v1RootCommentModel.Author, options); AppendProperty(sb, "preview", v1RootCommentModel.Preview, options); sb.Append("\"comments\":"); AppendCommentList(sb, v1RootCommentModel.Comments, options); sb.Append("]}"); return(Content(sb.ToString(), "application/json"));