.NET Fiddle

CSharp · Console

/Program.cs

using System;
using System.Linq;
using System.Collections.Generic;
using System.Text.Json;

public class Program
{
	public static void Main()
	{
		Console.WriteLine("Hello World");
		var permissions = new List<Permission>()
		{
			new(){ ObjectId = "1", ObjectType = "link", Scope = "link:read", AccountId = "1", GroupId = null },
			new(){ ObjectId = "1", ObjectType = "link", Scope = "link:read", AccountId = "2", GroupId = null },
			new(){ ObjectId = "1", ObjectType = "link", Scope = "link:read", AccountId = null, GroupId = "1" },
			new(){ ObjectId = "1", ObjectType = "link", Scope = "link:write", AccountId = "2", GroupId = null },
			new(){ ObjectId = "2", ObjectType = "link", Scope = "link:read", AccountId = "1", GroupId = null },
		};
		var result = permissions.GroupBy(r=> r.ObjectId).Select(r=> new {
			r.Key,
			InnerGroups = r.GroupBy(q=> q.Scope.Replace("link:","")).Select(q=> new {
				Scope = q.Key,
				Accounts =  q.Where(z=> z.AccountId != null).Select(z=> z.AccountId).ToArray(),
				Groups = q.Where(z=> z.GroupId != null).Select(z=> z.GroupId).ToArray()
			})
		})
			.ToDictionary(r=> r.Key,r=> r.InnerGroups.ToDictionary(q=> q.Scope,q=> new {q.Accounts,q.Groups}));
		
		var serialized = JsonSerializer.Serialize(result,new JsonSerializerOptions{ WriteIndented=true });
		serialized.Dump();
	}
}

public class Permission
{
    public string ObjectId { get; set; }
    public string ObjectType { get; set; }
    public string Scope { get; set; }
    public string? AccountId { get; set; }
    public string? GroupId { get; set; }
}

;